这可以用点自由风格表达吗?

Ono*_*cci 4 f# lambda-calculus pointfree

给出以下表达式来总结一个IEnumerable数字:

let sum l = l |> Seq.reduce(+)  //version a
Run Code Online (Sandbox Code Playgroud)

有可能消除这个论点 - 就像这样吗?

let sum = Seq.reduce(+)    //version b
Run Code Online (Sandbox Code Playgroud)

我从F#编译器(FS0030)得到一个错误,我似乎记得曾经看过有关"eta转换"的内容,但遗憾的是我对lambda calc的了解太少,无法跟踪如何涉及eta转换.

参数可以像版本b一样被删除吗?

有人请指点文献来解释eta转换以及它将如何在这段特殊代码中发挥作用吗?

FS0030:

stdin(1,5):错误FS0030:值限制.值'sum'被推断为具有泛型类型val sum:('_a - > int)当'_a:> seq要么使'sum'的参数显式,要么如果你不打算使它是通用的,添加类型注释.

Tar*_*mil 7

"Eta转换"仅仅意味着添加或删除参数.你遇到的问题叫做价值限制.在ML语言中,声明为值的值,即.声明没有显式参数,不能有泛型类型,即使它有一个函数类型.是一些相关的文献.这个想法是为了防止ref单元格保存不同类型的值.例如,没有值限制,将允许以下程序:

let f : 'a -> 'a option =
    let r = ref None
    fun x ->
        let old = !r
        r := Some x
        old

f 3           // r := Some 3; returns None : int option
f "t"         // r := Some "t"; returns Some 3 : string option!!!
Run Code Online (Sandbox Code Playgroud)

正如kvb所说,如果你不打算将该函数设置为泛型,那么你可以添加一个类型签名并使用无点样式.


kvb*_*kvb 5

您可以使用点自由样式执行此操作,但需要添加(单态)类型注释:

let sum : int seq -> int = Seq.reduce (+)
Run Code Online (Sandbox Code Playgroud)


byt*_*ter 5

无点函数是一个值。
正如其他答案所说,F# 不允许通用。然而,它完美地允许通用函数。让我们sum通过添加一个假参数来转换为一个函数unit

let sum_attempt1() = Seq.reduce (+)
let v1 = [1.0; 2.0]     |> sum()    // float
// inferred by first usage:
// val sum_attempt1: unit -> (seq<float> -> float)
Run Code Online (Sandbox Code Playgroud)

这是可行的,尽管它还不是通用的。标记该函数inline可以解决问题:

let inline sum() = Seq.reduce (+)
// val sum: unit -> (seq<'a> -> 'a)

// Use
let v1 = [1; 2]         |> sum()    // int
let v2 = [1.0; 2.0]     |> sum()    // float
let v3 = ["foo"; "bar"] |> sum()    // string
Run Code Online (Sandbox Code Playgroud)