关于Steve Yegge关于服务器端Javascript的帖子的评论开始讨论类型系统在语言中的优点,这篇评论描述了:
......来自HM风格系统的例子,你可以得到这样的东西:
Run Code Online (Sandbox Code Playgroud)expected signature Int*Int->Int but got Int*Int->Int
你能给出一个函数定义(或两个?)和一个会产生错误的函数调用的例子吗?看起来在大型程序中调试可能相当困难.
另外,我可能在米兰达看到过类似的错误吗?(我15年没用过了,所以我对它的记忆含糊不清)
我想学习和使用ML,但那里有很多编译器.我需要:
我不需要:
在纯功能数据结构论文的第6.3.1章中说:
然后,每当我们从一个新元素和一个排名为0 ... r-1的树段创建一个新树时,我们只需将新元素与该段中的第一个根(即,0级树的根)进行比较).较小的元素成为新的根,较大的元素成为根的0级子元素.
问题是第3步导致两个等级1树,这与二项式堆冲突.
我误会了吗?
对于我的生活,我无法弄清楚如何在SML/NJ中使用更高阶的仿函数到任何实际的目的.
根据
SML/NJ关于实现特殊功能的文档,应该可以通过使用funsig关键字将一个仿函数指定为另一个仿函数.因此,给予签名
signature SIG = sig ... end
Run Code Online (Sandbox Code Playgroud)
SIG当应用于满足某些签名的结构时,我们应该能够指定一个生成满足模块的仿函数
SIG'.例如,
funsig Fn (S:SIG') = SIG
Run Code Online (Sandbox Code Playgroud)
通过Fn这种方式声明,我们应该(能够定义另一个将该仿函数作为参数的仿函数.即,我们可以定义一个参数化在另一个参数化模块上的模块,并且可能在前者中使用后者;因此:
functor Fn' (functor Fn:SIG) =
struct
...
structure S' = Fn (S:SIG')
...
end
Run Code Online (Sandbox Code Playgroud)
这在理论上看起来都不错,但我无法弄清楚如何实际使用这种模式.
以下是我尝试使用此模式的两个实例,但却发现它不切实际:
对于我的第一次尝试,只是玩游戏,我试图制作一个仿函数,它将实现一个有序集的仿函数,并生成一个处理整数集的模块(不是很有用,但它可以让你参数化一组给定的键入不同的集合实现).我可以定义以下结构,它们将编译(使用新泽西州标准ML v110.7):
structure IntOrdKey : ORD_KEY
= struct
type ord_key = int
val compare = Int.compare
end
funsig SET_FN (KEY:ORD_KEY) = ORD_SET
functor IntSetFn (functor SetFn:SET_FN) =
struct
structure Set = SetFn (IntOrdKey) …Run Code Online (Sandbox Code Playgroud) 我是OCaml的新手,我现在正在尝试实现一个函数,该函数返回列表x中索引的给定列表的元素列表y.
例如,该函数应执行以下计算: [5,6,7,8], [0, 3] => [5, 8]
我不知道如何在ML中存储临时变量,并且不清楚它是如何工作的.但我知道如何从给定指定索引的列表中查找元素.
任何想法将不胜感激,但我想使用递归函数并避免使用该List模块.
每个人都可以向我解释这段代码吗?
let safe_division n = function
| 0 -> failwith "divide by 0"
| m -> n / m
Run Code Online (Sandbox Code Playgroud)
当我EXCUTE safeDiv 3 0,什么是m与n在这种情况下?
一般情况下,函数何时匹配第一个和第二个模式?
我对OCaml中的弱多态性有点困惑.
请参阅以下代码片段,我在其中定义一个函数remember:
let remember x =
let cache = ref None in
match !cache with
| Some y -> y
| None -> cache := Some x; x
;;
Run Code Online (Sandbox Code Playgroud)
编译器可以推断出多态类型'a -> 'a,并cache在本地使用.
但是当我修改上面的代码时
let remember =
let cache = ref None in
(fun x -> match !cache with
| Some y -> y
| None -> cache := Some x; x)
;;
Run Code Online (Sandbox Code Playgroud)
编译器推断出弱多态类型'_a -> '_a,似乎cache在调用之间共享remember.
为什么编译器在这里推断出弱多态类型以及为什么要 …
我处于一个很大的困境,请使用以下代码编写ML:
val x = 1
fun f(y) = x + y
val x = 2
val y = 3
val z = f (x + y)
Run Code Online (Sandbox Code Playgroud)
z的值是6.现在,如果我在python中编写相同的代码,则z的值将为7.并且两种语言都声称(实际上教授这些语言的教师声称这样)具有词法/静态范围.但看起来只有ML才能通过使用在调用f时定义f函数时创建的环境来实现它
任何指针将不胜感激!
谢谢!
runST是一个Haskell函数,它通过类型静态地约束资源的可用生命周期.为此,它使用rank-2多态性.标准ML的简单类型系统仅提供秩-1多态性.
标准ML是否仍然可以使用类型将资源的生命周期约束到类似的最终结果?
此页面和此页面演示了一些重构代码的方法,只需要更简单的类型.如果我理解正确,核心是将表达式包装起来,以便它被上下文中可能的观察所取代,这些观察是有限的.这种技术一般吗?可以将它,或相关编码,具有一些可使用像(显然在签名不相同)runST,以防止从被包裹的表达逸出值的类型被观察?如果是这样,怎么样?
我想象的场景是这样的:
magicRunSTLikeThing (fn resource =>
(* do things with resource *)
(* return a value that most definitely doesn't contain resource *)
)
Run Code Online (Sandbox Code Playgroud)
...其中magic...提供了用户提供的代码无法以任何方式共享的资源.显然,这样一个简单的界面具有单个库函数是不可能的,但也许有各种层次的包装和手工内联和提取......?
我已经看到了这一点,但如果我理解正确(...很可能不是),那实际上并不会阻止对资源的所有引用进行共享,只能确保对它的一个引用必须"关闭".
基本上我想在SML中实现安全类型的显式(非推断的MLKit样式)区域.
Benjamin C. Pierce 在其类型和编程语言一书的第23.8节中写道:
系统F的另一个充分研究的限制是由Leivant(1983)引入的rank-2多态性 [...].当类型被绘制为树时,如果没有从其根到∀量词的路径传递到2个或更多箭头的左侧,则称类型为等级2.[...]在rank-2系统中,所有类型都被限制为等级2.这个系统比prenex(ML)片段稍强一些,因为它可以为更多无类型的lambda术语分配类型.
Kfoury和Tiuryn(1990)证明了系统F的秩-2片段的类型重建的复杂性与ML的相同(即,DExptime-complete).Kfoury和Wells(1999)给出了秩2系统的第一个正确的类型重建算法,并且表明系统F的等级3和更高的类型重建是不可判定的.
因此,知道秩-2多态的类型推断是可判定的,并且自1999年以来就已知算法.Haskell支持其RankNTypes语言扩展,但它支持rank-n多态.
哪些语言(如果有的话)实现了rank-2参数多态而不是System F?
由于类型推断是可判定的并且没有最差的复杂性,为什么既没有SML也没有OCaml扩展多态性到-2级?
为什么我们没有在野外看到和阅读更多关于rank-2多态性的信息?