“价值限制”是否意味着没有更高阶的函数式编程?
绝对不! 值限制几乎不会干扰高阶函数式编程。它所做的是将多态函数的一些应用程序——而不是高阶函数——限制在顶层。
让我们看看你的例子。您的问题是oops
andoops2
既是身份功能又是 type forall 'a . 'a -> 'a
。换句话说,每个都是多态值。但右边不是所谓的“句法值”;它是一个功能应用程序。(函数应用程序不允许返回多态值,因为如果是,您可以使用会颠覆类型系统的可变引用和列表构造一个 hacky 函数;也就是说,您可以编写一个终止函数类型 type forall 'a 'b . 'a -> 'b
。
幸运的是,在几乎所有实际情况下,所讨论的多态值都是一个函数,您可以通过 eta-expanding 来定义它:
let oops x = simple "" x
这个习语看起来有一些运行时成本,但取决于内联器和优化器,编译器可以摆脱它——只是糟糕的类型检查器有问题。
该oops2
示例比较麻烦,因为您必须对值构造函数进行打包和解包:
let oops2 = F(fun x -> let F f = get "" in f x)
这个比较繁琐,但是匿名函数fun x -> ...
是句法值,F
是数据类型构造函数,应用于句法值的构造函数也是句法值,而 Bob 是你的叔叔。的打包和解包F
都将被编译到身份函数中,因此将oops2
编译为与.oops
当您希望运行时计算返回像None
or之类的多态值时,情况会更加糟糕[]
。正如 Nathan Sanders 所暗示的,您可以使用如下简单的表达式来违反值限制rev []
:
Standard ML of New Jersey v110.67 [built: Sun Oct 19 17:18:14 2008]
- val l = rev [];
stdIn:1.5-1.15 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val l = [] : ?.X1 list
-
那里没有更高阶的东西!然而价值限制仍然适用。
实际上,值限制对高阶函数的定义和使用没有任何障碍;你只是eta-expand。