我很困惑为什么第三个功能不起作用:
let generate1 = id
let generate2 = let a = 1
id
let generate3 = printfn "hi"
id
虽然前2个很好,但最后一个吐出
error FS0030: Value restriction. The value 'generate3' has been inferred to have generic type
val generate3 : ('_a -> '_a)
Either make the arguments to 'generate3' explicit or, if you do not intend for it to be generic, add a type annotation.
答案 0 :(得分:6)
我不会尝试explain value restriction,但我会尝试理清这三个值之间的语义差异。
generate1
只是id
的别名,所以我们在那里很好。
generate3
在返回id
之前会进行一些计算,达到值限制。
那么为什么generate2
不会像generate3
那样达到价值限制?因为编译器可以看到let x = 1 in id
在语义上等同于id
:1
是一个常量表达式而x
未在let ... in ...
表达式的主体中使用,所以编译器可以并且确实将它们抛弃了。另一方面,如果将1
替换为潜在的副作用,如sin 2.3
(sin
是纯粹的,但编译器无法证明它),那么编译器无法安全地减少表达式,因此与generate3
一样达到了值限制。