{-# LANGUAGE CPP #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
#if __GLASGOW_HASKELL__ >= 702 && __GLASGOW_HASKELL__ < 710
{-# LANGUAGE Trustworthy #-}
#endif
module Data.Functor.Day.Curried
(
Curried(..)
, toCurried, fromCurried, applied, unapplied
, adjointToCurried, curriedToAdjoint
, composedAdjointToCurried, curriedToComposedAdjoint
, liftCurried, lowerCurried, rap
) where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
import Data.Functor.Adjunction
import Data.Functor.Day
import Data.Functor.Identity
newtype Curried g h a =
Curried { runCurried :: forall r. g (a -> r) -> h r }
instance Functor g => Functor (Curried g h) where
fmap f (Curried g) = Curried (g . fmap (.f))
{-# INLINE fmap #-}
instance (Functor g, g ~ h) => Applicative (Curried g h) where
pure a = Curried (fmap ($a))
{-# INLINE pure #-}
Curried mf <*> Curried ma = Curried (ma . mf . fmap (.))
{-# INLINE (<*>) #-}
liftCurried :: Applicative f => f a -> Curried f f a
liftCurried fa = Curried (<*> fa)
{-# INLINE liftCurried #-}
lowerCurried :: Applicative f => Curried f g a -> g a
lowerCurried (Curried f) = f (pure id)
{-# INLINE lowerCurried #-}
rap :: Functor f => Curried f g (a -> b) -> Curried g h a -> Curried f h b
rap (Curried mf) (Curried ma) = Curried (ma . mf . fmap (.))
{-# INLINE rap #-}
applied :: Functor f => Day f (Curried f g) a -> g a
applied (Day fb (Curried fg) bca) = fg (bca <$> fb)
{-# INLINE applied #-}
unapplied :: g a -> Curried f (Day f g) a
unapplied ga = Curried $ \ fab -> Day fab ga id
{-# INLINE unapplied #-}
toCurried :: (forall x. Day g k x -> h x) -> k a -> Curried g h a
toCurried h ka = Curried $ \gar -> h (Day gar ka id)
{-# INLINE toCurried #-}
fromCurried :: Functor f => (forall a. k a -> Curried f h a) -> Day f k b -> h b
fromCurried f (Day fc kd cdb) = runCurried (f kd) (cdb <$> fc)
{-# INLINE fromCurried #-}
adjointToCurried :: Adjunction f u => u a -> Curried f Identity a
adjointToCurried ua = Curried (Identity . rightAdjunct (<$> ua))
{-# INLINE adjointToCurried #-}
curriedToAdjoint :: Adjunction f u => Curried f Identity a -> u a
curriedToAdjoint (Curried m) = leftAdjunct (runIdentity . m) id
{-# INLINE curriedToAdjoint #-}
curriedToComposedAdjoint :: Adjunction f u => Curried f h a -> u (h a)
curriedToComposedAdjoint (Curried m) = leftAdjunct m id
{-# INLINE curriedToComposedAdjoint #-}
composedAdjointToCurried :: (Functor h, Adjunction f u) => u (h a) -> Curried f h a
composedAdjointToCurried uha = Curried $ rightAdjunct (\b -> fmap b <$> uha)
{-# INLINE composedAdjointToCurried #-}