# [Haskell] generic currying (type classes and functional dependencies)

Esa Pulkkinen esa.pulkkinen at kotiposti.net
Wed May 12 00:03:54 EDT 2004

```In message <1084241553.27784.25.camel at localhost>, Duncan Coutts writes:
>I'm trying to write a generic curry (& uncurry) function that works for
>functions of any arity. I have a couple solutions that nearly work, both
>involving type classes.
[SNIP]
>Any insight or suggestions would be interesting.

Here's one solution, which I think is more general than what you ask,
but I guess it should work as well. It's based on adjunctions from
category theory:

class (Functor path, Functor space) =>
Adjunction path space | path -> space, space -> path where
leftAdjunct :: (path top -> bot) -> top -> space bot
unit :: top -> space (path top)
rightAdjunct :: (top -> space bot) -> path top -> bot
counit :: path (space bot) -> bot
-- minimum required impl: unit xor leftAdjunct
-- minimum required impl: counit xor rightAdjunct
leftAdjunct f = fmap f . unit
rightAdjunct g = counit . fmap g

-- Here are some instances for different arities:

instance Adjunction ((,) a) ((->) a) where
unit t = \arg -> (arg,t)
counit (x,f) = f x

newtype Func2 a b c = Func2 (a -> b -> c)
-- Func2 is only needed due to syntax of partial type constructor application

instance Adjunction ((,,) a b) (Func2 a b) where
unit t = Func2 (\arg1 arg2 -> (arg1,arg2,t))
counit (arg1,arg2,Func2 f) = f arg1 arg2

instance Functor ((,,) a b) where
fmap f (x,y,z) = (x,y,f z)

instance Functor (Func2 a b) where
fmap f (Func2 g) = Func2 (\a b -> f (g a b))