module Control.Comonad.Reader where
import Control.Bifunctor
import Control.Bifunctor.Pair
import Control.Monad.Instances
import Control.Comonad.Reader.Class
import Control.Comonad
import Control.Arrow ((&&&))
data ReaderC r a = ReaderC r a
runReaderC (ReaderC r a) = (r,a)
instance ComonadReader r (ReaderC r) where
askC (ReaderC r _) = r
instance Functor (ReaderC r) where
fmap f = uncurry ReaderC . second f . runReaderC
instance Comonad (ReaderC r) where
extract (ReaderC _ a) = a
duplicate (ReaderC e a) = ReaderC e (ReaderC e a)
instance Bifunctor ReaderC where
bimap f g = uncurry ReaderC . bimap f g . runReaderC
newtype ReaderCT w r a = ReaderCT { runReaderCT :: w (r, a) }
instance Comonad w => ComonadReader r (ReaderCT w r) where
askC = fst . extract . runReaderCT
instance Functor f => Functor (ReaderCT f b) where
fmap f = ReaderCT . fmap (fmap f) . runReaderCT
instance Comonad w => Comonad (ReaderCT w b) where
extract = snd . extract . runReaderCT
duplicate = ReaderCT . liftW (fst . extract &&& ReaderCT) . duplicate . runReaderCT
instance Functor f => Bifunctor (ReaderCT f) where
bimap f g = ReaderCT . fmap (bimap f g) . runReaderCT
instance Comonad ((,)e) where
extract = snd
duplicate ~(e,a) = (e,(e,a))
instance ComonadReader e ((,)e) where
askC = fst