I've been learning currying in Haskell and now trying to write the Haskell type signature of a function in curried form, whose uncurried form has an argument pair of type (x, y) and a value of type x as its result. I think the correct approach would be f :: (y,x) -> x
, but I'm not sure. Is it correct, and if not, why?
CodePudding user response:
You can let ghci
do this for you.
> f = undefined :: (a, b) -> c
> :t curry f
curry f :: a -> b -> c
You can uncurry the result to get back the original type.
> :t uncurry (curry f)
uncurry (curry f) :: (a, b) -> c
The actual implementation of curry
is, perhaps, more enlightening.
curry :: ((a, b) -> c) -> a -> b -> c
curry f = \x -> \y -> f (x, y)
If f
expects a tuple, then curry f
simply packages its two arguments into a tuple to pass to f
.
Examples are hard to come by, as functions in Haskell are usually fully curried already. But we can explicitly uncurry a binary operator to construct an example.
> ( ) 3 5
8
> f = uncurry ( )
> f (3, 5)
8
> (curry f) 3 5
8
As an aside, the type you suggested is what you would get by inserting a call to flip
between currying and uncurrying a function:
> :t uncurry . flip . curry
uncurry . flip . curry :: ((b, a) -> c) -> (a, b) -> c
To see this in action, you'd have to pick a non-commutative operator, like ( )
.
> strconcat = uncurry ( )
> strconcat ("foo", "bar")
"foobar"
> (uncurry . flip . curry) strconcat ("foo", "bar")
"barfoo"
CodePudding user response:
Just swapping the elements of the tuple is not currying. You have to get rid of the tuple altogether. You can do that by taking the first element of the tuple as argument and returning a function which takes the second element of the tuple and finally returns the result type. In your case the type would be f :: x -> (y -> x)
, these parenthesis are redundant, it is the same as f :: x -> y -> x
. This is the curried form.