{-# LANGUAGE Rank2Types #-} module Data.TrieMap.CPair where newtype CPair a b = CP (forall r . (a -> b -> r) -> r) pairFromC :: CPair a b -> (a, b) pairFromC (CP k) = k (,) pairToC :: (a, b) -> CPair a b pairToC p = CP (\ k -> uncurry k p) instance Functor (CPair a) where fmap f (CP k) = CP (\ g -> k (\ x -> g x . f)) on1st :: (a -> b) -> CPair a c -> CPair b c on1st f (CP k) = CP (\ g -> k (g . f)) on2nd :: (b -> c) -> CPair a b -> CPair a c on2nd f (CP k) = CP (\ g -> k (\ x -> g x . f)) cP :: a -> b -> CPair a b x `cP` y = CP (\ k -> k x y) cpFst :: CPair a b -> a cpFst = cpUncurry const cpSnd :: CPair a b -> b cpSnd = cpUncurry (flip const) cpUncurry :: (a -> b -> r) -> CPair a b -> r cpUncurry f (CP k) = k f cpCurry :: (CPair a b -> r) -> a -> b -> r cpCurry f a b = f (a `cP` b)