值限制:类型"bar"已被推断为具有泛型类型

Bit*_*ler 4 f#

在下面的代码片段中,我看不出为什么我必须编写fg函数的方式foo以及为什么它不能像函数bar尝试那样工作.

let f a b = a,b
let g (a : 'a) (b : 'a) = a

let (>!) f1 f2 =
    fun a b ->
        let (x,y) = f1 a b
        f2 x y

let foo = fun a b -> (f >! g) a b
let bar = f >! g
Run Code Online (Sandbox Code Playgroud)

任何人都可以向我解释,为什么bar不工作?鉴于它foo也具有通用类型,对我来说没有任何意义.

Fyo*_*kin 7

foo是一个函数,bar而是一个值.是的,它是函数类型的值,但仍然是值.那里有一个微妙的区别.

F#编译器可以"看到"这foo是一个函数,因为它看到了fun ->正确的函数let.

bar,在另一方面,是一个真正的价值-通过调用不同的功能(运营商获得的结果>!).F#有一条规则(称为"值限制")说(在日常术语中)值(与函数不同)不能具有泛型类型,除非明确指定泛型参数,因此有效地使其成为"类型函数".(它有点复杂,请阅读以下链接以获取完整图片)

这不是特定于F#,但是ML的其他非纯变体也具有此特性.下面是这个规则的F#的讨论,这里是为SML的讨论.

  • 简单来说,这不是函数是第一类的问题,而是语法和定义的问题.还有其他类似的例子:模块中定义的函数与静态类上定义的函数不同,静态类与本地上下文中定义的函数不同.另一个例子 - 即使函数是"值",它们的通用性也不包括在内 - 即你不能在不实例化的情况下传递泛型函数. (2认同)
  • 从提供的链接我终于明白它是什么.F#不保证函数是无副作用并返回不可变对象.因此,编译器必须防止这种情况起作用,否则会出现病态情况,这些情况确实不起作用.这也向我解释了为什么同样的方法在haskell中有效,而在F#(ML)中却没有.非常感谢您的见解. (2认同)