module Data.Distributive
( Distributive(..)
, fmapDefault
) where
import Control.Applicative
import Control.Comonad
import Control.Monad.Trans.Identity
import Control.Monad.Trans.Reader
import Control.Monad.Instances ()
import Data.Functor.Identity
class Functor g => Distributive g where
cotraverse :: Comonad w => (w a -> b) -> w (g a) -> g b
distribute :: Comonad w => w (g a) -> g (w a)
cotraverse f = fmap f . distribute
distribute = cotraverse id
instance Distributive Identity where
cotraverse f = Identity . f . fmap runIdentity
distribute = Identity . fmap runIdentity
instance Distributive ((->)e) where
distribute w e = fmap ($e) w
instance Distributive g => Distributive (ReaderT e g) where
distribute w = ReaderT $ \e -> distribute (fmap (flip runReaderT e) w)
instance Distributive g => Distributive (IdentityT g) where
cotraverse f w = IdentityT $ cotraverse f (runIdentityT <$> w)
distribute w = IdentityT $ distribute (runIdentityT <$> w)
fmapDefault :: Distributive g => (a -> b) -> g a -> g b
fmapDefault f = cotraverse (f . runIdentity) . Identity