{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
#if __GLASGOW_HASKELL__ >= 706
{-# LANGUAGE PolyKinds #-}
#endif
{-# LANGUAGE MultiParamTypeClasses #-}
#if __GLASGOW_HASKELL__ >= 702 && __GLASGOW_HASKELL__ < 710
{-# LANGUAGE Trustworthy #-}
#endif
module Control.Comonad.Density
( Density(..)
, liftDensity
, densityToAdjunction, adjunctionToDensity
, densityToLan, lanToDensity
) where
import Control.Applicative
import Control.Comonad
import Control.Comonad.Trans.Class
import Data.Functor.Apply
import Data.Functor.Adjunction
import Data.Functor.Extend
import Data.Functor.Kan.Lan
data Density k a where
Density :: (k b -> a) -> k b -> Density k a
instance Functor (Density f) where
fmap f (Density g h) = Density (f . g) h
{-# INLINE fmap #-}
instance Extend (Density f) where
duplicated (Density f ws) = Density (Density f) ws
{-# INLINE duplicated #-}
instance Comonad (Density f) where
duplicate (Density f ws) = Density (Density f) ws
{-# INLINE duplicate #-}
extract (Density f a) = f a
{-# INLINE extract #-}
instance ComonadTrans Density where
lower (Density f c) = extend f c
{-# INLINE lower #-}
instance Apply f => Apply (Density f) where
Density kxf x <.> Density kya y =
Density (\k -> kxf (fmap fst k) (kya (fmap snd k))) ((,) <$> x <.> y)
{-# INLINE (<.>) #-}
instance Applicative f => Applicative (Density f) where
pure a = Density (const a) (pure ())
{-# INLINE pure #-}
Density kxf x <*> Density kya y =
Density (\k -> kxf (fmap fst k) (kya (fmap snd k))) (liftA2 (,) x y)
{-# INLINE (<*>) #-}
liftDensity :: Comonad w => w a -> Density w a
liftDensity = Density extract
{-# INLINE liftDensity #-}
densityToAdjunction :: Adjunction f g => Density f a -> f (g a)
densityToAdjunction (Density f v) = fmap (leftAdjunct f) v
{-# INLINE densityToAdjunction #-}
adjunctionToDensity :: Adjunction f g => f (g a) -> Density f a
adjunctionToDensity = Density counit
{-# INLINE adjunctionToDensity #-}
lanToDensity :: Lan f f a -> Density f a
lanToDensity (Lan f v) = Density f v
{-# INLINE lanToDensity #-}
densityToLan :: Density f a -> Lan f f a
densityToLan (Density f v) = Lan f v
{-# INLINE densityToLan #-}