当未柯里化形式已知时,在 Haskell 中柯里化

And*_*ger 3 haskell function currying

我一直在学习 Haskell 中的柯里化,现在尝试以柯里化形式编写函数的 Haskell 类型签名,其非柯里化形式有一个 (x, y) 类型的参数对和一个 x 类型的值作为其结果。我认为正确的方法是f :: (y,x) -> x,但我不确定。这是正确的吗?如果不正确,为什么?

che*_*ner 6

你可以让它ghci为你做这件事。

> f = undefined :: (a, b) -> c
> :t curry f
curry f :: a -> b -> c
Run Code Online (Sandbox Code Playgroud)

您可以对结果进行取消柯里化以恢复原始类型。

> :t uncurry (curry f)
uncurry (curry f) :: (a, b) -> c
Run Code Online (Sandbox Code Playgroud)

实际的实施curry也许更具启发性。

curry :: ((a, b) -> c) -> a -> b -> c
curry f = \x -> \y -> f (x, y)
Run Code Online (Sandbox Code Playgroud)

如果f需要一个元组,则curry f只需将其两个参数打包到一个元组中以传递给f.

例子很难找到,因为 Haskell 中的函数通常已经完全柯里化了。但是我们可以显式地取消二元运算符来构造一个示例。

> (+) 3 5
8
> f = uncurry (+)
> f (3, 5)
8
> (curry f) 3 5
8
Run Code Online (Sandbox Code Playgroud)

flip顺便说一句,您建议的类型是通过在柯里化和取消柯里化函数之间插入调用所得到的类型:

> :t uncurry . flip . curry
uncurry . flip . curry :: ((b, a) -> c) -> (a, b) -> c
Run Code Online (Sandbox Code Playgroud)

要看到它的实际效果,您必须选择一个非交换运算符,例如(++)

> strconcat = uncurry (++)
> strconcat ("foo", "bar")
"foobar"
> (uncurry . flip . curry) strconcat ("foo", "bar")
"barfoo"
Run Code Online (Sandbox Code Playgroud)

  • 它们相当于 [*alpha conversion*](https://wiki.haskell.org/Alpha_conversion),这是一种奇特的说法,表示特定变量的名称并不重要,只要一致使用即可贯穿整个表达式。 (5认同)