在知道未柯里化形式时在 haskell 中柯里化

currying in haskell when the uncurried form is known

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

只是交换元组的元素不是柯里化。你必须完全摆脱元组。您可以通过将元组的第一个元素作为参数并返回一个函数来实现,该函数采用元组的第二个元素,最后 returns 结果类型。在您的情况下,类型将是 f :: x -> (y -> x),这些括号是多余的,它与 f :: x -> y -> x 相同。这是咖喱形式。

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

> f = undefined :: (a, b) -> c
> :t curry f
curry f :: a -> b -> c

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

> :t uncurry (curry f)
uncurry (curry f) :: (a, b) -> c

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

curry :: ((a, b) -> c) -> a -> b -> c
curry f = \x -> \y -> f (x, y)

如果f需要一个元组,那么curry f只是将它的两个参数打包成一个元组传递给f

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

> (+) 3 5
8
> f = uncurry (+)
> f (3, 5)
8
> (curry f) 3 5
8

顺便说一句,您建议的类型是通过在 currying 和 uncurrying 函数之间插入对 flip 的调用而得到的类型:

> :t uncurry . flip . curry
uncurry . flip . curry :: ((b, a) -> c) -> (a, b) -> c

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

> strconcat = uncurry (++)
> strconcat ("foo", "bar")
"foobar"
> (uncurry . flip . curry) strconcat ("foo", "bar")
"barfoo"