Published on January 29, 2013

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.

```
{-# LANGUAGE TypeFamilies, DefaultSignatures, UndecidableInstances #-}
class Uncurry a where
type Uncurried1 b a
type Uncurried1 b a = b -> a
unc1 :: (b -> a) -> Uncurried1 b a
default unc1 :: (b -> a) -> (b -> a)
unc1 = id
type Uncurried a
type Uncurried a = a
unc :: a -> Uncurried a
default unc :: a -> a
unc = id
instance Uncurry y => Uncurry (x -> y) where
type Uncurried1 z (x -> y) = Uncurried1 (z, x) y
unc1 = unc1 . uncurry
type Uncurried (x -> y) = Uncurried1 x y
unc = unc1
```

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

`instance Uncurry Double`

`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.