{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
#if __GLASGOW_HASKELL__ >= 707
{-# LANGUAGE RoleAnnotations #-}
#endif
module Control.Lens.Internal.Context
( IndexedFunctor(..)
, IndexedComonad(..)
, IndexedComonadStore(..)
, Sellable(..)
, Context(..), Context'
, Pretext(..), Pretext'
, PretextT(..), PretextT'
) where
import Prelude ()
import Control.Arrow
import qualified Control.Category as C
import Control.Comonad
import Control.Comonad.Store.Class
import Control.Lens.Internal.Indexed
import Control.Lens.Internal.Prelude
import Data.Profunctor.Rep
import Prelude hiding ((.),id)
class IndexedFunctor w where
ifmap :: (s -> t) -> w a b s -> w a b t
class IndexedFunctor w => IndexedComonad w where
#if __GLASGOW_HASKELL__ >= 708
{-# MINIMAL iextract, (iduplicate | iextend) #-}
#endif
iextract :: w a a t -> t
iduplicate :: w a c t -> w a b (w b c t)
iduplicate = iextend id
{-# INLINE iduplicate #-}
iextend :: (w b c t -> r) -> w a c t -> w a b r
iextend f = ifmap f . iduplicate
{-# INLINE iextend #-}
class IndexedComonad w => IndexedComonadStore w where
ipos :: w a c t -> a
ipeek :: c -> w a c t -> t
ipeek c = iextract . iseek c
{-# INLINE ipeek #-}
ipeeks :: (a -> c) -> w a c t -> t
ipeeks f = iextract . iseeks f
{-# INLINE ipeeks #-}
iseek :: b -> w a c t -> w b c t
iseeks :: (a -> b) -> w a c t -> w b c t
iexperiment :: Functor f => (b -> f c) -> w b c t -> f t
iexperiment bfc wbct = (`ipeek` wbct) <$> bfc (ipos wbct)
{-# INLINE iexperiment #-}
context :: w a b t -> Context a b t
context wabt = Context (`ipeek` wabt) (ipos wabt)
{-# INLINE context #-}
class Corepresentable p => Sellable p w | w -> p where
sell :: p a (w a b b)
data Context a b t = Context (b -> t) a
instance IndexedFunctor Context where
ifmap f (Context g t) = Context (f . g) t
{-# INLINE ifmap #-}
instance IndexedComonad Context where
iextract (Context f a) = f a
{-# INLINE iextract #-}
iduplicate (Context f a) = Context (Context f) a
{-# INLINE iduplicate #-}
iextend g (Context f a) = Context (g . Context f) a
{-# INLINE iextend #-}
instance IndexedComonadStore Context where
ipos (Context _ a) = a
{-# INLINE ipos #-}
ipeek b (Context g _) = g b
{-# INLINE ipeek #-}
ipeeks f (Context g a) = g (f a)
{-# INLINE ipeeks #-}
iseek a (Context g _) = Context g a
{-# INLINE iseek #-}
iseeks f (Context g a) = Context g (f a)
{-# INLINE iseeks #-}
iexperiment f (Context g a) = g <$> f a
{-# INLINE iexperiment #-}
context = id
{-# INLINE context #-}
instance Functor (Context a b) where
fmap f (Context g t) = Context (f . g) t
{-# INLINE fmap #-}
instance a ~ b => Comonad (Context a b) where
extract (Context f a) = f a
{-# INLINE extract #-}
duplicate (Context f a) = Context (Context f) a
{-# INLINE duplicate #-}
extend g (Context f a) = Context (g . Context f) a
{-# INLINE extend #-}
instance a ~ b => ComonadStore a (Context a b) where
pos = ipos
{-# INLINE pos #-}
peek = ipeek
{-# INLINE peek #-}
peeks = ipeeks
{-# INLINE peeks #-}
seek = iseek
{-# INLINE seek #-}
seeks = iseeks
{-# INLINE seeks #-}
experiment = iexperiment
{-# INLINE experiment #-}
instance Sellable (->) Context where
sell = Context id
{-# INLINE sell #-}
type Context' a = Context a a
newtype Pretext p a b t = Pretext { runPretext :: forall f. Functor f => p a (f b) -> f t }
type Pretext' p a = Pretext p a a
instance IndexedFunctor (Pretext p) where
ifmap f (Pretext k) = Pretext (fmap f . k)
{-# INLINE ifmap #-}
instance Functor (Pretext p a b) where
fmap = ifmap
{-# INLINE fmap #-}
instance Conjoined p => IndexedComonad (Pretext p) where
iextract (Pretext m) = runIdentity $ m (arr Identity)
{-# INLINE iextract #-}
iduplicate (Pretext m) = getCompose $ m (Compose #. distrib sell C.. sell)
{-# INLINE iduplicate #-}
instance (a ~ b, Conjoined p) => Comonad (Pretext p a b) where
extract = iextract
{-# INLINE extract #-}
duplicate = iduplicate
{-# INLINE duplicate #-}
instance Conjoined p => IndexedComonadStore (Pretext p) where
ipos (Pretext m) = getConst $ coarr m $ arr Const
{-# INLINE ipos #-}
ipeek a (Pretext m) = runIdentity $ coarr m $ arr (\_ -> Identity a)
{-# INLINE ipeek #-}
ipeeks f (Pretext m) = runIdentity $ coarr m $ arr (Identity . f)
{-# INLINE ipeeks #-}
iseek a (Pretext m) = Pretext (lmap (lmap (const a)) m)
{-# INLINE iseek #-}
iseeks f (Pretext m) = Pretext (lmap (lmap f) m)
{-# INLINE iseeks #-}
iexperiment f (Pretext m) = coarr m (arr f)
{-# INLINE iexperiment #-}
context (Pretext m) = coarr m (arr sell)
{-# INLINE context #-}
instance (a ~ b, Conjoined p) => ComonadStore a (Pretext p a b) where
pos = ipos
{-# INLINE pos #-}
peek = ipeek
{-# INLINE peek #-}
peeks = ipeeks
{-# INLINE peeks #-}
seek = iseek
{-# INLINE seek #-}
seeks = iseeks
{-# INLINE seeks #-}
experiment = iexperiment
{-# INLINE experiment #-}
instance Corepresentable p => Sellable p (Pretext p) where
sell = cotabulate $ \ w -> Pretext (`cosieve` w)
{-# INLINE sell #-}
newtype PretextT p (g :: * -> *) a b t = PretextT { runPretextT :: forall f. Functor f => p a (f b) -> f t }
#if __GLASGOW_HASKELL__ >= 707
type role PretextT representational nominal nominal nominal nominal
#endif
type PretextT' p g a = PretextT p g a a
instance IndexedFunctor (PretextT p g) where
ifmap f (PretextT k) = PretextT (fmap f . k)
{-# INLINE ifmap #-}
instance Functor (PretextT p g a b) where
fmap = ifmap
{-# INLINE fmap #-}
instance Conjoined p => IndexedComonad (PretextT p g) where
iextract (PretextT m) = runIdentity $ m (arr Identity)
{-# INLINE iextract #-}
iduplicate (PretextT m) = getCompose $ m (Compose #. distrib sell C.. sell)
{-# INLINE iduplicate #-}
instance (a ~ b, Conjoined p) => Comonad (PretextT p g a b) where
extract = iextract
{-# INLINE extract #-}
duplicate = iduplicate
{-# INLINE duplicate #-}
instance Conjoined p => IndexedComonadStore (PretextT p g) where
ipos (PretextT m) = getConst $ coarr m $ arr Const
{-# INLINE ipos #-}
ipeek a (PretextT m) = runIdentity $ coarr m $ arr (\_ -> Identity a)
{-# INLINE ipeek #-}
ipeeks f (PretextT m) = runIdentity $ coarr m $ arr (Identity . f)
{-# INLINE ipeeks #-}
iseek a (PretextT m) = PretextT (lmap (lmap (const a)) m)
{-# INLINE iseek #-}
iseeks f (PretextT m) = PretextT (lmap (lmap f) m)
{-# INLINE iseeks #-}
iexperiment f (PretextT m) = coarr m (arr f)
{-# INLINE iexperiment #-}
context (PretextT m) = coarr m (arr sell)
{-# INLINE context #-}
instance (a ~ b, Conjoined p) => ComonadStore a (PretextT p g a b) where
pos = ipos
{-# INLINE pos #-}
peek = ipeek
{-# INLINE peek #-}
peeks = ipeeks
{-# INLINE peeks #-}
seek = iseek
{-# INLINE seek #-}
seeks = iseeks
{-# INLINE seeks #-}
experiment = iexperiment
{-# INLINE experiment #-}
instance Corepresentable p => Sellable p (PretextT p g) where
sell = cotabulate $ \ w -> PretextT (`cosieve` w)
{-# INLINE sell #-}
instance (Profunctor p, Contravariant g) => Contravariant (PretextT p g a b) where
contramap _ = (<$) (error "contramap: PretextT")
{-# INLINE contramap #-}
coarr :: (Representable q, Comonad (Rep q)) => q a b -> a -> b
coarr qab = extract . sieve qab
{-# INLINE coarr #-}