Skip to content

Instantly share code, notes, and snippets.

@chpatrick
Last active August 29, 2015 14:19
Show Gist options
  • Save chpatrick/e9cf011ca1a5e5976d05 to your computer and use it in GitHub Desktop.
Save chpatrick/e9cf011ca1a5e5976d05 to your computer and use it in GitHub Desktop.
Generalized uncurry without OverlappingInstances or other evil extensions
{-# LANGUAGE DataKinds, TypeFamilies, MultiParamTypeClasses, FlexibleInstances, GADTs, TypeOperators, FlexibleContexts, ConstraintKinds #-}
import Data.Tagged
type family FunResult f where
FunResult (a -> b) = FunResult b
FunResult x = x
type family FunArgs f where
FunArgs (a -> b) = a ': FunArgs b
FunArgs x = '[]
data HList ts where
Nil :: HList '[]
Cons :: t -> HList ts -> HList (t ': ts)
class Uncurry' (as :: [ * ]) o f where
guncurry' :: Tagged as (f -> HList as -> o)
instance Uncurry' as o b => Uncurry' (a ': as) o (a -> b) where
guncurry' = Tagged $ \f (x `Cons` xs) -> untag guncurry' (f x) xs
instance Uncurry' '[] r r where
guncurry' = Tagged $ \x Nil -> x
type Uncurry as o f = (as ~ FunArgs f, o ~ FunResult f, Uncurry' as o f)
type as =-> o = HList as -> o
guncurry :: Uncurry as o f => f -> as =-> o
guncurry = untag guncurry'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment