这可以用无点风格表达吗?

Posted

技术标签:

【中文标题】这可以用无点风格表达吗?【英文标题】:Can this be expressed in point free style? 【发布时间】:2013-10-07 17:06:21 【问题描述】:

给定以下表达式来对数字的 IEnumerable 求和:

let sum l = l |> Seq.reduce(+)  //version a

是否可以像这样消除争论?

let sum = Seq.reduce(+)    //version b

我从 F# 编译器 (FS0030) 收到一个错误,我似乎记得曾经看到过一些关于“eta 转换”的内容,但不幸的是,我对 lambda calc 的了解太有限,无法理解 eta 转换是如何涉及的。

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

请有人向我指出可以解释 eta 转换以及它如何在这段特定代码中发挥作用的文献吗?

FS0030:

stdin(1,5):错误 FS0030:值限制。值“总和”已 推断具有泛型类型 val sum : ('_a -> int) when '_a :> seq 将参数明确地传递给 'sum' 或者,如果您不打算这样做 泛型,添加类型注释。

【问题讨论】:

l 在版本 a 中做了什么?您能否提醒我们(在问题正文中)FS0030 是什么? 您的意思是 let sum l = Seq.reduce (+) l 用于版本 a 吗? 好吧,正如您从错误中看到的(并且可能知道),F# 不允许泛型值。 F# 仅有限支持无点样式。 @petebu 谢谢——代码已修复。 【参考方案1】:

“Eta 转换”仅表示添加或删除参数。您遇到的问题称为值限制。在 ML 语言中,声明为值的值,即。没有显式参数声明,不能有泛型类型,即使它有一个函数类型。 Here 是一些相关文献。这个想法是为了防止 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!!!

正如 kvb 所说,如果您不希望函数是泛型的,那么您可以添加类型签名并使用无点样式。

【讨论】:

或许可以简单的表述为:ML语言中的函数可以是闭包,而且由于ML是静态类型的,所以在使用前必须在引用环境中消除类型的歧义。【参考方案2】:

你可以用无点样式来做,但是你需要添加一个(单态)类型注释:

let sum : int seq -> int = Seq.reduce (+)

【讨论】:

谢谢@kvb;我还想知道是否有人可以向我指出有关 eta 转换的更多信息。【参考方案3】:

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

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

这可行,虽然它还不是通用的。标记函数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

【讨论】:

有趣的想法——在函数上添加内联。

以上是关于这可以用无点风格表达吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用无点递归实现使用 Ramda 删除对象中的空值?

以无点的方式映射seq中值的值

可以在 VSCode 中获得 pycharm 风格的“使用 Python 控制台运行”功能吗?

c 风格的字符串安全吗?

为啥运行带有 ECMAScript 风格支持的 .Net 正则表达式 \A

这种视图风格可能吗?