f# - 反向柯里化(Currying)?

标签 f# functional-programming currying higher-order-functions

我想以某种方式组合函数。请在伪代码(不是 F#)中考虑这两个函数

F1 = x + y
F2 = F1 * 10 // note I did not specify arguments for F1, 'reverse curry' for lack of a better word

我想让 F# 做的是弄清楚,因为
let F1 x y = x + y
//val F1 : int -> int -> int

代码 let F2 = F1 * 10会给我与 F1 相同的签名:val F2 : int -> int -> int ,并调用 F2 2 3将导致 50: (2 + 3) * 10。这将是相当聪明的......

发生的事情完全不同。第一行按预期进行:
let F1 x y = x + y
//val F1 : int -> int -> int

但是当我添加第二行 let F2 = F1 * 10它抛出了 F#。它提示the type int does not match the type 'a -> 'b -> 'c和那个 F1 现在 requires member ( + ) .

我当然可以这样拼写:
let F1(x, y) = x + y
let F2(x, y) = F1(x, y) * 10

但现在我还不如使用 C#,我们不再那么遥远了。元组参数破坏了 F# 的许多优雅。此外,我的真实函数 F1 和 F2 的参数远不止 2 个,所以这让我眼花缭乱,这正是我想通过使用 F# 来躲避的。像这样说会更自然:
let F1 x y = x + y
let F2 = F1 * 10

有什么办法我可以(几乎)做到这一点?

额外积分:这些错误消息到底发生了什么?为什么第二行let F2 = F1 * 10改变第一个打字?

提前感谢您的想法,

格特-扬

更新
两个(几乎)做所描述的事情。

一个使用元组。第二行看起来有点古怪,工作正常。小缺点是我现在不能使用柯里化(Currying),否则我将不得不添加更多古怪的代码。
let F1 (a, b) = a + b
let F2 = F1 >> (*) 10

F2(2, 3) // returns 50

另一种方法是使用记录。乍一看,这更直接,更容易理解,但需要更多的代码和仪式。确实去掉了 F# 的一些优雅,看起来更像 C#。
type Arg (a, b) =
    member this.A = a
    member this.B = b

let F1 (a:Arg) = a.A + a.B
let F2 (a:Arg) = F1(a) * 10

F2 (Arg(2, 3)) // returns 50

最佳答案

一般来说,没有这种模式。使用 larsmans 建议的组合器(如 curryuncurry )是一种选择,但我认为结果比显式版本更易读且更长。

如果你经常使用这个特定的模式,你可以定义一个运算符来将一个函数(有两个参数)乘以一个标量:

let ( ** ) f x = fun a b -> (f a b) * x

let F1 x y = x + y
let F2 = F1 ** 10

不幸的是,您不能将标准数字运算符( * 等)的实现添加到现有类型(例如 'a -> 'b -> int )。但是,这是非常频繁的请求(它对其他事情很有用)。或者,您可以将函数包装到一些提供重载数字运算符的对象中(并包含一些 Invoke 用于运行函数的方法)。

我认为一个合适的名称是提升 - 你正在提升 *运算符(处理整数)转换为处理返回整数的函数的版本。它类似于使用 * 时在 C# 编译器中完成的提升。使用可为空的类型。

解释错误消息 - 它提示表达式 F1 * 10 :

error FS0001: The type 'int' does not match the type ''a -> 'b -> 'c'



我认为这意味着编译器正在尝试为 * 查找实例化。运算符(operator)。从右侧计算,这应该是 int ,所以它认为左边也应该是int - 但它实际上是两个参数的函数 - 类似于 'a -> 'b -> c' .

关于f# - 反向柯里化(Currying)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5882527/

相关文章:

c# - F# 中的模式匹配比 C# 中的 If else/switch 慢得多吗?

haskell - 是否有 F# 工具/库将值可视化为图形(如 Haskell 的 vacuum)?

Dartz - 离开 Either

list - Erlang打印2列表

casting - #(井号/井号)在类型签名中是什么意思?

azure - DocumentDb 上的文档未被替换

scala - 将 Map 作为 (flatMap) 映射函数传递会导致错误

scala - 如何在scala curry函数中绑定(bind)第二个参数?

javascript - 取消 javascript 中 n 个参数的柯里化(Currying)函数

Scala:如果类构造函数不起作用的默认值