Generic uncurry

Published on

For the next version of SmallCheck I needed a generic uncurry function in Haskell. To my surprise, I couldn’t google anything simple and ready to use.

So here it is, for future reference.

You also need to make the final type an instance of Uncurry. For example, if you need to uncurry Int -> Bool -> Double, Double has to be an instance of Uncurry. But thanks to default method signatures and associated type synonym defaults, it is as easy as

Uncurry1 and unc1 are implementation details. The useful parts are Uncurry, which converts the type to its uncurried version, and unc, which uncurries the function itself.

After loading the code in ghci, you can see that it works by:

*Uncurry> :kind! Uncurried (Int -> Bool -> Char -> Double)
Uncurried (Int -> Bool -> Char -> Double) :: *
= ((Int, Bool), Char) -> Double

*Uncurry> :t unc $ \x y z -> (x + y * z :: Double)
unc $ \x y z -> (x + y * z :: Double)
  :: ((Double, Double), Double) -> Double

*Uncurry> unc (\x y z -> (x + y * z :: Double)) ((1,2),3)
7.0

I tested this with GHC 7.6, but I think it should work with GHC 7.4 as well.