在F#中,我可以定义一个add1
函数
let add1 x = x + 1
然后我可以将add2
定义为自己调用的add1
函数
let add2 x = add1 (add1 x)
或者通过将add1
函数与其自身组成
let add2 = add1 >> add1
我试图在F#中实现lambda演算组合器,第一个是Identity
let I x = x
然后我尝试定义Identity
的{{1}}
Identity
但这会导致以下编译错误:
值限制。值“ II”已推断为具有通用值 类型 val II:('_a->'_a)可以使'II'的参数显式,或者,如果您不打算将其泛化,则添加一个类型 注释
我可以将其定义为
let II = I >> I
我是F#的新手,好奇为什么?
答案 0 :(得分:1)
此错误与函数组合本身无关,与Value Restriction
有关。发生这种情况是因为F#编译器会尽可能推断类型,但尽管可以轻松地泛化函数,但不能泛化 value (即使您的值实际上是一个函数)。
This answer可以帮助您避免此问题,但是基本上您应该指定一个输入参数:
let II x = (I>>I) x
或
let II x = I >> I <| x
答案 1 :(得分:0)
@kagetogi是正确的。
F#编译器希望将值解析为具体类型,并且在您第一次使用该函数时将尝试这样做。所以这失败了:
let I x = x
let II = I >> I
但这可行:
let I x = x
let II = I >> I
II 5 |> printfn "%A"
此处II
的类型为int->int
。这意味着以下操作失败:
let I x = x
let II = I >> I
II 5 |> printfn "%A"
II 5.0 |> printfn "%A"
因为第二个呼叫期望int
而不是float
。
这就是为什么在F#中,管道|>
运算符比组合运算符>>
更为可取的原因。
let I x = x
let II x = x |> I |> I
let II' x = x |> (I >> I)
现在,II
的通用类型为'a->'a
。
它们都最终实现了功能组合。
添加代码注释也可以:
let II<'a> : 'a->'a = I >> I