F#-自身编写函数时出错

时间:2018-10-13 07:01:42

标签: f#

在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#的新手,好奇为什么?

2 个答案:

答案 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