我一直在学习 Haskell 中的柯里化(Currying),现在尝试以柯里化(Currying)形式编写函数的 Haskell 类型签名,其非柯里化(Currying)形式有一个 (x, y) 类型的参数对和一个 x 类型的值作为其结果.我认为正确的方法是 f::(y,x) -> x
,但我不确定。是否正确,如果不正确,为什么?
最佳答案
你可以让 ghci
为你做这件事。
> f = undefined :: (a, b) -> c
> :t curry f
curry f :: a -> b -> c
您可以对结果进行 uncurry 以取回原始类型。
> :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 中的函数通常已经完全柯里化(Currying)了。但是我们可以显式地 uncurry 一个二元运算符来构造一个例子。
> (+) 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"
关于function - 当非 curry 形式已知时,在haskell中进行柯里化(Currying),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69286631/