{-# LANGUAGE TypeFamilies #-} import Data.Kind (Type) import Data.Monoid (Sum(..)) class TupArgs tup where type TupFun tup r :: Type applyTupFun :: TupFun tup r -> tup -> r instance TupArgs () where type TupFun () r = r applyTupFun x _ = x instance TupArgs (a, b) where type TupFun (a, b) r = a -> b -> r applyTupFun f (x, y) = f x y instance TupArgs (a, b, c) where type TupFun (a, b, c) r = a -> b -> c -> r applyTupFun f (x, y, z) = f x y z foo :: TupArgs tup => tup -> TupFun tup r -> r foo tup f = applyTupFun f tup data T v a = T a deriving (Show) instance Num a => Num (T v a) where T a + T b = T (a + b) fromInteger = T . fromInteger -- other methods elided ver :: a -> T v a ver = T main :: IO () main = do let balanceBefore = T 42 :: T Bool Int -- whatever, I chose a 'v' print $ foo (balanceBefore, ver 2) (\x y -> x + y)