representable-functors 2.5 → 3.0
raw patch · 11 files changed
+869/−849 lines, 11 filesdep −data-lensdep ~comonaddep ~comonad-transformersdep ~comonads-fd
Dependencies removed: data-lens
Dependency ranges changed: comonad, comonad-transformers, comonads-fd, free, keys, semigroupoids
Files
- Control/Comonad/Representable/Store.hs +0/−116
- Control/Monad/Representable/Reader.hs +0/−157
- Control/Monad/Representable/State.hs +0/−218
- Data/Functor/Corepresentable.hs +0/−122
- Data/Functor/Representable.hs +0/−227
- representable-functors.cabal +10/−9
- src/Control/Comonad/Representable/Store.hs +121/−0
- src/Control/Monad/Representable/Reader.hs +160/−0
- src/Control/Monad/Representable/State.hs +218/−0
- src/Data/Functor/Corepresentable.hs +122/−0
- src/Data/Functor/Representable.hs +238/−0
− Control/Comonad/Representable/Store.hs
@@ -1,116 +0,0 @@-{-# LANGUAGE TypeFamilies- , FlexibleContexts- , FlexibleInstances- , MultiParamTypeClasses- , UndecidableInstances #-}-------------------------------------------------------------------------- |--- Module : Control.Comonad.Representable.Store--- Copyright : (c) Edward Kmett & Sjoerd Visscher 2011--- License : BSD3--- --- Maintainer : ekmett@gmail.com--- Stability : experimental--- --- A generalized Store comonad, parameterized by a Representable functor.--- The representation of that functor serves as the index of the store.------------------------------------------------------------------------module Control.Comonad.Representable.Store- ( Store- , store- , runStore- , StoreT(..)- , storeT- , runStoreT- , pos- , peek- , peeks- , seek- , seeks- ) where--import Control.Comonad-import Control.Applicative-import Data.Key-import Data.Functor.Apply-import Data.Semigroup-import Control.Comonad.Hoist.Class-import Control.Comonad.Env.Class-import Control.Comonad.Traced.Class-import Control.Comonad.Cofree.Class-import Control.Comonad.Trans.Class-import Control.Comonad.Store.Class-import Control.Monad.Identity-import Data.Functor.Representable---- | A memoized store comonad parameterized by a representable functor @g@, where --- the representatation of @g@, @Key g@ is the index of the store.----type Store g = StoreT g Identity---- | Construct a store comonad computation from a function and a current index.--- (The inverse of 'runStore'.)-store :: Representable g- => (Key g -> a) -- ^ computation- -> Key g -- ^ index- -> Store g a-store = storeT . Identity---- | Unwrap a state monad computation as a function.--- (The inverse of 'state'.)-runStore :: Indexable g- => Store g a -- ^ a store to access- -> (Key g -> a, Key g) -- ^ initial state-runStore (StoreT (Identity ga) k) = (index ga, k)---- ------------------------------------------------------------------------------ | A store transformer comonad parameterized by:------ * @g@ - A representable functor used to memoize results for an index @Key g@------ * @w@ - The inner comonad.-data StoreT g w a = StoreT (w (g a)) (Key g)--storeT :: (Functor w, Representable g) => w (Key g -> a) -> Key g -> StoreT g w a -storeT = StoreT . fmap tabulate--runStoreT :: (Functor w, Indexable g) => StoreT g w a -> (w (Key g -> a), Key g)-runStoreT (StoreT w s) = (index <$> w, s)--instance (Comonad w, Representable g, Key g ~ s) => ComonadStore s (StoreT g w) where- pos (StoreT _ s) = s- peek s (StoreT w _) = extract w `index` s- peeks f (StoreT w s) = extract w `index` f s- seek s (StoreT w _) = StoreT w s- seeks f (StoreT w s) = StoreT w (f s)--instance (Functor w, Functor g) => Functor (StoreT g w) where- fmap f (StoreT w s) = StoreT (fmap (fmap f) w) s--instance (Apply w, Semigroup (Key g), Representable g) => Apply (StoreT g w) where- StoreT ff m <.> StoreT fa n = StoreT (apRep <$> ff <.> fa) (m <> n)--instance (Applicative w, Semigroup (Key g), Monoid (Key g), Representable g) => Applicative (StoreT g w) where- pure a = StoreT (pure (pureRep a)) mempty- StoreT ff m <*> StoreT fa n = StoreT (apRep <$> ff <*> fa) (m `mappend` n)--instance (Extend w, Representable g) => Extend (StoreT g w) where- duplicate (StoreT wf s) = StoreT (extend (tabulate . StoreT) wf) s--instance (Comonad w, Representable g) => Comonad (StoreT g w) where- extract (StoreT wf s) = index (extract wf) s--instance Indexable g => ComonadTrans (StoreT g) where- lower (StoreT w s) = fmap (`index` s) w--instance ComonadHoist (StoreT g) where- cohoist (StoreT w s) = StoreT (Identity (extract w)) s--instance (ComonadTraced m w, Representable g) => ComonadTraced m (StoreT g w) where- trace m = trace m . lower--instance (ComonadEnv m w, Representable g) => ComonadEnv m (StoreT g w) where - ask = ask . lower--instance (Representable g, ComonadCofree f w) => ComonadCofree f (StoreT g w) where- unwrap (StoreT w s) = fmap (`StoreT` s) (unwrap w)
− Control/Monad/Representable/Reader.hs
@@ -1,157 +0,0 @@-{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, CPP, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, TypeSynonymInstances #-}-{-# OPTIONS_GHC -fenable-rewrite-rules -fno-warn-orphans #-}-------------------------------------------------------------------------- |--- Module : Control.Monad.Representable.Reader--- Copyright : (c) Edward Kmett 2011,--- (c) Conal Elliott 2008--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental------ Representable functors on Hask all monads, being isomorphic to--- a reader monad.-------------------------------------------------------------------------module Control.Monad.Representable.Reader- (- -- * Representable functor monad- Reader, runReader- -- * Monad Transformer- , ReaderT(..), readerT, runReaderT- , ask- , local- , module Data.Functor.Representable- ) where--import Control.Applicative-import Control.Comonad-import Control.Monad.Reader.Class-import Control.Monad.Writer.Class as Writer-import Control.Monad.Trans.Class-import Control.Monad.IO.Class-import Data.Distributive-import Data.Key-import Data.Functor.Bind-import Data.Functor.Identity-import Data.Functor.Representable-import Data.Foldable-import Data.Traversable-import Data.Semigroup-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Prelude hiding (lookup,zipWith)--type Reader f = ReaderT f Identity--runReader :: Indexable f => Reader f b -> Key f -> b-runReader = fmap runIdentity . runReaderT---- * This 'representable monad transformer' transforms any monad @m@ with a 'Representable' 'Monad'.--- This monad in turn is also representable if @m@ is 'Representable'.-newtype ReaderT f m b = ReaderT { getReaderT :: f (m b) }--readerT :: Representable f => (Key f -> m b) -> ReaderT f m b-readerT = ReaderT . tabulate--runReaderT :: Indexable f => ReaderT f m b -> Key f -> m b-runReaderT = index . getReaderT--type instance Key (ReaderT f m) = (Key f, Key m)--instance (Functor f, Functor m) => Functor (ReaderT f m) where- fmap f = ReaderT . fmap (fmap f) . getReaderT--instance (Indexable f, Indexable m) => Indexable (ReaderT f m) where- index = uncurry . fmap index . index . getReaderT--instance (Representable f, Representable m) => Representable (ReaderT f m) where- tabulate = ReaderT . tabulate . fmap tabulate . curry--instance (Representable f, Apply m) => Apply (ReaderT f m) where- ReaderT ff <.> ReaderT fa = ReaderT (unrep ((<.>) <$> Rep ff <.> Rep fa))--instance (Representable f, Applicative m) => Applicative (ReaderT f m) where- pure = ReaderT . pureRep . pure- ReaderT ff <*> ReaderT fa = ReaderT (unrep ((<*>) <$> Rep ff <*> Rep fa))--instance (Representable f, Bind m) => Bind (ReaderT f m) where- ReaderT fm >>- f = ReaderT $ tabulate (\a -> index fm a >>- flip index a . getReaderT . f)--instance (Representable f, Monad m) => Monad (ReaderT f m) where- return = ReaderT . pureRep . return- ReaderT fm >>= f = ReaderT $ tabulate (\a -> index fm a >>= flip index a . getReaderT . f)--#if __GLASGOW_HASKELL >= 704--instance (Representable f, Monad m, Key f ~ e) => MonadReader e (ReaderT f m) where- ask = ReaderT (tabulate return)- local f m = readerT $ \r -> runReaderT m (f r)-#if MIN_VERSION_transformers(0,3,0)- reader = readerT . fmap return-#endif--#endif--instance Representable f => MonadTrans (ReaderT f) where- lift = ReaderT . pureRep--instance (Representable f, Distributive m) => Distributive (ReaderT f m) where- distribute = ReaderT . fmapRep distribute . unrep . collect (Rep . getReaderT)--instance (Representable f, Keyed m) => Keyed (ReaderT f m) where- mapWithKey f = ReaderT . mapWithKeyRep (\k -> mapWithKey (f . (,) k)) . getReaderT--instance (Indexable f, Lookup m) => Lookup (ReaderT f m) where- lookup (k,k') (ReaderT fm) = lookup k' (index fm k)--instance (Representable f, Representable m, Semigroup (Key f), Semigroup (Key m)) => Extend (ReaderT f m) where- extend = extendRep- duplicate = duplicateRep--instance (Representable f, Zip m) => Zip (ReaderT f m) where- zipWith f (ReaderT as) (ReaderT bs) = ReaderT $ tabulate $ \i -> zipWith f (index as i) (index bs i)--instance (Representable f, ZipWithKey m) => ZipWithKey (ReaderT f m) where- zipWithKey f (ReaderT as) (ReaderT bs) = ReaderT $ tabulate $ \i -> zipWithKey (f . (,) i) (index as i) (index bs i)--instance (Representable f, Representable m, Semigroup (Key f), Semigroup (Key m), Monoid (Key f), Monoid (Key m)) => Comonad (ReaderT f m) where- extract = extractRep--instance (Representable f, MonadIO m) => MonadIO (ReaderT f m) where- liftIO = lift . liftIO--instance (Representable f, MonadWriter w m) => MonadWriter w (ReaderT f m) where- tell = lift . tell- listen (ReaderT m) = ReaderT $ tabulate $ Writer.listen . index m- pass (ReaderT m) = ReaderT $ tabulate $ Writer.pass . index m---- misc. instances that can exist, but aren't particularly about representability--instance (Adjustable f, Adjustable m) => Adjustable (ReaderT f m) where- adjust f (kf,km) = ReaderT . adjust (adjust f km) kf . getReaderT--instance (Foldable f, Foldable m) => Foldable (ReaderT f m) where- foldMap f = foldMap (foldMap f) . getReaderT--instance (Foldable1 f, Foldable1 m) => Foldable1 (ReaderT f m) where- foldMap1 f = foldMap1 (foldMap1 f) . getReaderT--instance (FoldableWithKey f, FoldableWithKey m) => FoldableWithKey (ReaderT f m) where- foldMapWithKey f = foldMapWithKey (\k -> foldMapWithKey (f . (,) k)) . getReaderT--instance (FoldableWithKey1 f, FoldableWithKey1 m) => FoldableWithKey1 (ReaderT f m) where- foldMapWithKey1 f = foldMapWithKey1 (\k -> foldMapWithKey1 (f . (,) k)) . getReaderT--instance (Traversable f, Traversable m) => Traversable (ReaderT f m) where- traverse f = fmap ReaderT . traverse (traverse f) . getReaderT--instance (Traversable1 f, Traversable1 m) => Traversable1 (ReaderT f m) where- traverse1 f = fmap ReaderT . traverse1 (traverse1 f) . getReaderT--instance (Representable f, TraversableWithKey f, TraversableWithKey m) => TraversableWithKey (ReaderT f m) where- traverseWithKey f = fmap ReaderT . traverseWithKey (\k -> traverseWithKey (f . (,) k)) . getReaderT--instance (Representable f, TraversableWithKey1 f, TraversableWithKey1 m) => TraversableWithKey1 (ReaderT f m) where- traverseWithKey1 f = fmap ReaderT . traverseWithKey1 (\k -> traverseWithKey1 (f . (,) k)) . getReaderT
− Control/Monad/Representable/State.hs
@@ -1,218 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-------------------------------------------------------------------------- |--- Module : Control.Monad.Representable.State--- Copyright : (c) Edward Kmett & Sjoerd Visscher 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental------ A generalized State monad, parameterized by a Representable functor.--- The representation of that functor serves as the state.------------------------------------------------------------------------module Control.Monad.Representable.State- ( State- , runState- , evalState- , execState- , mapState- , StateT(..)- , stateT- , runStateT- , evalStateT- , execStateT- , mapStateT- , liftCallCC- , liftCallCC'- , get- , gets- , put- , modify- ) where--import Control.Applicative-import Data.Key-import Data.Functor.Bind-import Data.Functor.Bind.Trans-import Control.Monad.State.Class-import Control.Monad.Cont.Class-import Control.Monad.Reader.Class-import Control.Monad.Writer.Class-import Control.Monad.Free.Class-import Control.Monad.Trans.Class-import Control.Monad.Identity-import Data.Functor.Representable---- ------------------------------------------------------------------------------ | A memoized state monad parameterized by a representable functor @g@, where--- the representatation of @g@, @Key g@ is the state to carry.------ The 'return' function leaves the state unchanged, while @>>=@ uses--- the final state of the first computation as the initial state of--- the second.-type State g = StateT g Identity----- | Unwrap a state monad computation as a function.--- (The inverse of 'state'.)-runState :: Indexable g- => State g a -- ^ state-passing computation to execute- -> Key g -- ^ initial state- -> (a, Key g) -- ^ return value and final state-runState m = runIdentity . runStateT m---- | Evaluate a state computation with the given initial state--- and return the final value, discarding the final state.------ * @'evalState' m s = 'fst' ('runState' m s)@-evalState :: Indexable g- => State g a -- ^state-passing computation to execute- -> Key g -- ^initial value- -> a -- ^return value of the state computation-evalState m s = fst (runState m s)---- | Evaluate a state computation with the given initial state--- and return the final state, discarding the final value.------ * @'execState' m s = 'snd' ('runState' m s)@-execState :: Indexable g- => State g a -- ^state-passing computation to execute- -> Key g -- ^initial value- -> Key g -- ^final state-execState m s = snd (runState m s)---- | Map both the return value and final state of a computation using--- the given function.------ * @'runState' ('mapState' f m) = f . 'runState' m@-mapState :: Functor g => ((a, Key g) -> (b, Key g)) -> State g a -> State g b-mapState f = mapStateT (Identity . f . runIdentity)---- ------------------------------------------------------------------------------ | A state transformer monad parameterized by:------ * @g@ - A representable functor used to memoize results for a state @Key g@------ * @m@ - The inner monad.------ The 'return' function leaves the state unchanged, while @>>=@ uses--- the final state of the first computation as the initial state of--- the second.-newtype StateT g m a = StateT { getStateT :: g (m (a, Key g)) }--stateT :: Representable g => (Key g -> m (a, Key g)) -> StateT g m a-stateT = StateT . tabulate--runStateT :: Indexable g => StateT g m a -> Key g -> m (a, Key g)-runStateT (StateT m) = index m--mapStateT :: Functor g => (m (a, Key g) -> n (b, Key g)) -> StateT g m a -> StateT g n b-mapStateT f (StateT m) = StateT (fmap f m)---- | Evaluate a state computation with the given initial state--- and return the final value, discarding the final state.------ * @'evalStateT' m s = 'liftM' 'fst' ('runStateT' m s)@-evalStateT :: (Indexable g, Monad m) => StateT g m a -> Key g -> m a-evalStateT m s = do- (a, _) <- runStateT m s- return a---- | Evaluate a state computation with the given initial state--- and return the final state, discarding the final value.------ * @'execStateT' m s = 'liftM' 'snd' ('runStateT' m s)@-execStateT :: (Indexable g, Monad m) => StateT g m a -> Key g -> m (Key g)-execStateT m s = do- (_, s') <- runStateT m s- return s'--instance (Functor g, Functor m) => Functor (StateT g m) where- fmap f = StateT . fmap (fmap (\ ~(a, s) -> (f a, s))) . getStateT--instance (Functor g, Indexable g, Bind m) => Apply (StateT g m) where- mf <.> ma = mf >>- \f -> fmap f ma--instance (Representable g, Functor m, Monad m) => Applicative (StateT g m) where- pure = StateT . leftAdjunctRep return- mf <*> ma = mf >>= \f -> fmap f ma--instance (Functor g, Indexable g, Bind m) => Bind (StateT g m) where- StateT m >>- f = StateT $ fmap (>>- rightAdjunctRep (runStateT . f)) m--instance (Representable g, Monad m) => Monad (StateT g m) where- return = StateT . leftAdjunctRep return- StateT m >>= f = StateT $ fmap (>>= rightAdjunctRep (runStateT . f)) m--instance Representable f => BindTrans (StateT f) where- liftB m = stateT $ \s -> fmap (\a -> (a, s)) m--instance Representable f => MonadTrans (StateT f) where- lift m = stateT $ \s -> liftM (\a -> (a, s)) m--instance (Representable g, Monad m, Key g ~ s) => MonadState s (StateT g m) where- get = stateT $ \s -> return (s, s)- put s = StateT $ pureRep $ return ((),s)-#if MIN_VERSION_transformers(0,3,0)- state f = stateT (return . f)-#endif---- get :: (Representable g, Monad m) => StateT g m (Key g)--- put :: (Applicative g, Monad m) => Key g -> StateT g m ()---- gets :: (Representable g, Monad m) => (Key g -> s) -> StateT g m s--- gets f = liftM f get---- modify :: (Representable g, Monad m) => (Key g -> Key g) -> StateT g m ()--- modify f = stateT $ \s -> return ((), f s)--instance (Representable g, MonadReader e m) => MonadReader e (StateT g m) where- ask = lift ask- local = mapStateT . local--instance (Representable g, MonadWriter w m) => MonadWriter w (StateT g m) where- tell = lift . tell- listen = mapStateT $ \ma -> do- ((a,s'), w) <- listen ma- return ((a,w), s')- pass = mapStateT $ \ma -> pass $ do- ((a, f), s') <- ma- return ((a, s'), f)--instance (Representable g, MonadCont m) => MonadCont (StateT g m) where- callCC = liftCallCC' callCC--instance (Functor f, Representable g, MonadFree f m) => MonadFree f (StateT g m) where- wrap as = stateT $ \s -> wrap (fmap (`runStateT` s) as)--leftAdjunctRep :: Representable u => ((a, Key u) -> b) -> a -> u b-leftAdjunctRep f a = tabulate (\s -> f (a,s))--rightAdjunctRep :: Indexable u => (a -> u b) -> (a, Key u) -> b-rightAdjunctRep f ~(a, k) = f a `index` k---- | Uniform lifting of a @callCC@ operation to the new monad.--- This version rolls back to the original state on entering the--- continuation.-liftCallCC :: Representable g => ((((a,Key g) -> m (b,Key g)) -> m (a,Key g)) -> m (a,Key g)) ->- ((a -> StateT g m b) -> StateT g m a) -> StateT g m a-liftCallCC callCC' f = stateT $ \s ->- callCC' $ \c ->- runStateT (f (\a -> StateT $ pureRep $ c (a, s))) s---- | In-situ lifting of a @callCC@ operation to the new monad.--- This version uses the current state on entering the continuation.--- It does not satisfy the laws of a monad transformer.-liftCallCC' :: Representable g => ((((a,Key g) -> m (b,Key g)) -> m (a,Key g)) -> m (a,Key g)) ->- ((a -> StateT g m b) -> StateT g m a) -> StateT g m a-liftCallCC' callCC' f = stateT $ \s ->- callCC' $ \c ->- runStateT (f (\a -> stateT $ \s' -> c (a, s'))) s-
− Data/Functor/Corepresentable.hs
@@ -1,122 +0,0 @@-{-# LANGUAGE TypeFamilies, FlexibleContexts, FlexibleInstances #-}-{-# OPTIONS_GHC -fenable-rewrite-rules #-}--------------------------------------------------------------------------- |--- Module : Data.Functor.Corepresentable--- Copyright : (c) Edward Kmett 2011--- License : BSD3--- --- Maintainer : ekmett@gmail.com--- Stability : experimental--- --- Representable contravariant endofunctors over the category of Haskell --- types are isomorphic to @(_ -> r)@ and resemble mappings to a--- fixed range.-------------------------------------------------------------------------module Data.Functor.Corepresentable- ( - -- * Values- Value- -- * Contravariant Keyed- , Valued(..)- -- * Contravariant Indexed- , Coindexed(..)- -- * Representable Contravariant Functors- , Corepresentable(..)- -- * Default definitions- , contramapDefault- , contramapWithValueDefault- ) where--import Control.Monad.Reader-import Data.Functor.Contravariant-import Data.Functor.Product-import Data.Functor.Coproduct-import Prelude hiding (lookup)--type family Value (f :: * -> *)---- | Dual to 'Keyed'.-class Contravariant f => Valued f where- contramapWithValue :: (b -> Either a (Value f)) -> f a -> f b---- | Dual to 'Indexed'.-class Coindexed f where- coindex :: f a -> a -> Value f---- | A 'Functor' @f@ is 'Corepresentable' if 'corep' and 'coindex' witness an isomorphism to @(_ -> Value f)@.------ > tabulate . index = id--- > index . tabulate = id--- > tabulate . return f = return f--class (Coindexed f, Valued f) => Corepresentable f where- -- | > contramap f (corep g) = corep (g . f)- corep :: (a -> Value f) -> f a--{-# RULES-"corep/coindex" forall t. corep (coindex t) = t- #-}---- * Default definitions--contramapDefault :: Corepresentable f => (a -> b) -> f b -> f a-contramapDefault f = corep . (. f) . coindex --contramapWithValueDefault :: Corepresentable f => (b -> Either a (Value f)) -> f a -> f b-contramapWithValueDefault f p = corep $ either (coindex p) id . f---- * Dual arrows--type instance Value (Op r) = r--instance Valued (Op r) where- contramapWithValue = contramapWithValueDefault--instance Coindexed (Op r) where- coindex = getOp--instance Corepresentable (Op r) where- corep = Op---- * Predicates--type instance Value Predicate = Bool--instance Valued Predicate where- contramapWithValue = contramapWithValueDefault--instance Coindexed Predicate where- coindex = getPredicate--instance Corepresentable Predicate where- corep = Predicate---- * Products--type instance Value (Product f g) = (Value f, Value g)--instance (Valued f, Valued g) => Valued (Product f g) where- -- contramapWithValue :: (b -> Either a (Value f)) -> f a -> f b- contramapWithValue h (Pair f g) = Pair - (contramapWithValue (fmap fst . h) f)- (contramapWithValue (fmap snd . h) g)- -- (contramapWithValue (either id snd . h) g)- -- (either g snd . h)--instance (Coindexed f, Coindexed g) => Coindexed (Product f g) where- coindex (Pair f g) a = (coindex f a, coindex g a)--instance (Corepresentable f, Corepresentable g) => Corepresentable (Product f g) where- corep f = Pair (corep (fst . f)) (corep (snd . f))----- * Coproducts--type instance Value (Coproduct f g) = Either (Value f) (Value g)--instance (Coindexed f, Coindexed g) => Coindexed (Coproduct f g) where- coindex (Coproduct (Left f)) a = Left $ coindex f a - coindex (Coproduct (Right g)) a = Right $ coindex g a
− Data/Functor/Representable.hs
@@ -1,227 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# OPTIONS_GHC -fenable-rewrite-rules #-}-------------------------------------------------------------------------- |--- Module : Data.Functor.Representable--- Copyright : (c) Edward Kmett 2011--- License : BSD3--- --- Maintainer : ekmett@gmail.com--- Stability : experimental--- --- Representable endofunctors over the category of Haskell types are --- isomorphic to the reader monad and so inherit a very large number--- of properties for free.-------------------------------------------------------------------------module Data.Functor.Representable- (- -- * Representable Functors- Representable(..)- -- * Wrapped representable functors- , Rep(..)- -- ** Representable Lenses- , repLens- -- * Default definitions- -- ** Functor- , fmapRep- -- ** Distributive- , distributeRep- -- ** Keyed- , mapWithKeyRep- -- ** Apply/Applicative- , apRep- , pureRep- , liftR2- , liftR3- -- ** Bind/Monad- , bindRep- , bindWithKeyRep- -- ** Zip/ZipWithKey- , zipWithRep- , zipWithKeyRep- -- ** MonadReader- , askRep- , localRep- -- ** Extend- , duplicateRep- , extendRep- -- ** Comonad- , extractRep- ) where--import Control.Applicative-import Control.Comonad-import Control.Comonad.Trans.Class-import Control.Comonad.Trans.Traced-import Control.Comonad.Cofree-import Control.Monad.Trans.Identity-import Control.Monad.Reader-import Data.Distributive-import Data.Key-import Data.Functor.Bind-import Data.Functor.Identity-import Data.Functor.Compose-import Data.Functor.Product-import Data.Lens.Common-import qualified Data.Sequence as Seq-import Data.Semigroup hiding (Product)-import Prelude hiding (lookup)---- | A 'Functor' @f@ is 'Representable' if 'tabulate' and 'index' witness an isomorphism to @(->) x@.------ > tabulate . index = id--- > index . tabulate = id--- > tabulate . return f = return f--class (Functor f, Indexable f) => Representable f where- -- | > fmap f . tabulate = tabulate . fmap f- tabulate :: (Key f -> a) -> f a--{-# RULES-"tabulate/index" forall t. tabulate (index t) = t- #-}---- * Default definitions--fmapRep :: Representable f => (a -> b) -> f a -> f b-fmapRep f = tabulate . fmap f . index--mapWithKeyRep :: Representable f => (Key f -> a -> b) -> f a -> f b-mapWithKeyRep f = tabulate . (<*>) f . index--pureRep :: Representable f => a -> f a-pureRep = tabulate . const--bindRep :: Representable f => f a -> (a -> f b) -> f b-bindRep m f = tabulate (\a -> index (f (index m a)) a)--bindWithKeyRep :: Representable f => f a -> (Key f -> a -> f b) -> f b-bindWithKeyRep m f = tabulate (\a -> index (f a (index m a)) a)--askRep :: Representable f => f (Key f)-askRep = tabulate id--localRep :: Representable f => (Key f -> Key f) -> f a -> f a-localRep f m = tabulate (index m . f)--apRep :: Representable f => f (a -> b) -> f a -> f b-apRep f g = tabulate (index f <*> index g)--zipWithRep :: Representable f => (a -> b -> c) -> f a -> f b -> f c-zipWithRep f g h = tabulate $ \k -> f (index g k) (index h k)--zipWithKeyRep :: Representable f => (Key f -> a -> b -> c) -> f a -> f b -> f c-zipWithKeyRep f g h = tabulate $ \k -> f k (index g k) (index h k)--distributeRep :: (Representable f, Functor w) => w (f a) -> f (w a)-distributeRep wf = tabulate (\k -> fmap (`index` k) wf)--duplicateRep :: (Representable f, Semigroup (Key f)) => f a -> f (f a)-duplicateRep w = tabulate (\m -> tabulate (index w . (<>) m))--extendRep :: (Representable f, Semigroup (Key f)) => (f a -> b) -> f a -> f b-extendRep f w = tabulate (\m -> f (tabulate (index w . (<>) m)))--extractRep :: (Indexable f, Monoid (Key f)) => f a -> a-extractRep fa = index fa mempty---- | We extend lens across a representable functor, due to the preservation of limits.-repLens :: Representable f => Lens a b -> Lens (f a) (f b)-repLens l = lens (fmapRep (l ^$)) $ \a b -> unrep $ liftA2 (l ^=) (Rep a) (Rep b)---- * Instances--instance Representable Identity where- tabulate f = Identity (f ())--instance Representable m => Representable (IdentityT m) where- tabulate = IdentityT . tabulate--instance Representable ((->) e) where- tabulate = id--instance Representable m => Representable (ReaderT e m) where- tabulate = ReaderT . fmap tabulate . curry --instance (Representable f, Representable g) => Representable (Compose f g) where- tabulate = Compose . tabulate . fmap tabulate . curry--instance Representable w => Representable (TracedT s w) where- -- tabulate = TracedT . collect tabulate . curry- tabulate = TracedT . unrep . collect (Rep . tabulate) . curry--instance (Representable f, Representable g) => Representable (Product f g) where- tabulate f = Pair (tabulate (f . Left)) (tabulate (f . Right))--instance Representable f => Representable (Cofree f) where- tabulate f = f Seq.empty :< tabulate (\k -> tabulate (f . (k Seq.<|)))---newtype Rep f a = Rep { unrep :: f a }--type instance Key (Rep f) = Key f--instance Representable f => Representable (Rep f) where- tabulate = Rep . tabulate--instance Indexable f => Indexable (Rep f) where- index (Rep f) i = index f i--instance Representable f => Keyed (Rep f) where- mapWithKey = mapWithKeyRep--instance Indexable f => Lookup (Rep f) where- lookup = lookupDefault--instance Representable f => Functor (Rep f) where- fmap = fmapRep--instance Representable f => Apply (Rep f) where- (<.>) = apRep--instance Representable f => Applicative (Rep f) where- pure = pureRep- (<*>) = apRep--instance Representable f => Distributive (Rep f) where- distribute = distributeRep--instance Representable f => Bind (Rep f) where- (>>-) = bindRep--instance Representable f => Monad (Rep f) where- return = pureRep- (>>=) = bindRep--#if __GLASGOW_HASKELL__ >= 704-instance (Representable f, Key f ~ a) => MonadReader a (Rep f) where- ask = askRep- local = localRep-#endif--instance Representable f => Zip (Rep f) where- zipWith = zipWithRep--instance Representable f => ZipWithKey (Rep f) where- zipWithKey = zipWithKeyRep--instance (Representable f, Semigroup (Key f)) => Extend (Rep f) where- extend = extendRep--instance (Representable f, Semigroup (Key f), Monoid (Key f)) => Comonad (Rep f) where- extract = extractRep--instance ComonadTrans Rep where- lower (Rep f) = f--liftR2 :: Representable f => (a -> b -> c) -> f a -> f b -> f c-liftR2 f fa fb = tabulate $ \i -> f (index fa i) (index fb i)--liftR3 :: Representable f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d-liftR3 f fa fb fc = tabulate $ \i -> f (index fa i) (index fb i) (index fc i)
representable-functors.cabal view
@@ -1,6 +1,6 @@ name: representable-functors category: Monads, Functors, Data Structures-version: 2.5+version: 3.0 license: BSD3 cabal-version: >= 1.6 license-file: LICENSE@@ -20,6 +20,8 @@ location: git://github.com/ekmett/representable-functors.git library+ hs-source-dirs: src+ other-extensions: CPP FlexibleContexts@@ -34,19 +36,18 @@ build-depends: array >= 0.3.0.2 && < 0.5, base >= 4 && < 5,- comonad >= 1.1.1.5 && < 1.2,+ comonad >= 3.0 && < 3.1,+ comonad-transformers >= 3.0 && < 3.1,+ comonads-fd >= 3.0 && < 3.1, containers >= 0.3 && < 0.6, contravariant >= 0.2.0.1 && < 0.3, distributive >= 0.2.2 && < 0.3,+ free >= 3.0 && < 3.1,+ keys >= 3.0 && < 3.1, mtl >= 2.0.1.0 && < 2.2, semigroups >= 0.8.3.1 && < 0.9,- semigroupoids >= 1.3.1.2 && < 1.4,- transformers >= 0.2 && < 0.4,- keys >= 2.2 && < 2.3,- free >= 2.2 && < 2.3,- comonad-transformers >= 2.1.1.1 && < 2.2,- comonads-fd >= 2.1.1.1 && < 2.2,- data-lens >= 2.0.3 && < 2.11+ semigroupoids >= 3.0 && < 3.1,+ transformers >= 0.2 && < 0.4 exposed-modules: Data.Functor.Corepresentable
+ src/Control/Comonad/Representable/Store.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE TypeFamilies+ , FlexibleContexts+ , FlexibleInstances+ , MultiParamTypeClasses+ , UndecidableInstances #-}+----------------------------------------------------------------------+-- |+-- Module : Control.Comonad.Representable.Store+-- Copyright : (c) Edward Kmett & Sjoerd Visscher 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+--+-- A generalized Store comonad, parameterized by a Representable functor.+-- The representation of that functor serves as the index of the store.+----------------------------------------------------------------------+module Control.Comonad.Representable.Store+ ( Store+ , store+ , runStore+ , StoreT(..)+ , storeT+ , runStoreT+ , pos+ , peek+ , peeks+ , seek+ , seeks+ ) where++import Control.Comonad+import Control.Applicative+import Data.Key+import Data.Functor.Apply+import Data.Functor.Extend+import Data.Semigroup+import Control.Comonad.Hoist.Class+import Control.Comonad.Env.Class+import Control.Comonad.Traced.Class+import Control.Comonad.Cofree.Class+import Control.Comonad.Trans.Class+import Control.Comonad.Store.Class+import Control.Monad.Identity+import Data.Functor.Representable++-- | A memoized store comonad parameterized by a representable functor @g@, where+-- the representatation of @g@, @Key g@ is the index of the store.+--+type Store g = StoreT g Identity++-- | Construct a store comonad computation from a function and a current index.+-- (The inverse of 'runStore'.)+store :: Representable g+ => (Key g -> a) -- ^ computation+ -> Key g -- ^ index+ -> Store g a+store = storeT . Identity++-- | Unwrap a state monad computation as a function.+-- (The inverse of 'state'.)+runStore :: Indexable g+ => Store g a -- ^ a store to access+ -> (Key g -> a, Key g) -- ^ initial state+runStore (StoreT (Identity ga) k) = (index ga, k)++-- ---------------------------------------------------------------------------+-- | A store transformer comonad parameterized by:+--+-- * @g@ - A representable functor used to memoize results for an index @Key g@+--+-- * @w@ - The inner comonad.+data StoreT g w a = StoreT (w (g a)) (Key g)++storeT :: (Functor w, Representable g) => w (Key g -> a) -> Key g -> StoreT g w a+storeT = StoreT . fmap tabulate++runStoreT :: (Functor w, Indexable g) => StoreT g w a -> (w (Key g -> a), Key g)+runStoreT (StoreT w s) = (index <$> w, s)++instance (Comonad w, Representable g, Key g ~ s) => ComonadStore s (StoreT g w) where+ pos (StoreT _ s) = s+ peek s (StoreT w _) = extract w `index` s+ peeks f (StoreT w s) = extract w `index` f s+ seek s (StoreT w _) = StoreT w s+ seeks f (StoreT w s) = StoreT w (f s)++instance (Functor w, Functor g) => Functor (StoreT g w) where+ fmap f (StoreT w s) = StoreT (fmap (fmap f) w) s++instance (Apply w, Semigroup (Key g), Representable g) => Apply (StoreT g w) where+ StoreT ff m <.> StoreT fa n = StoreT (apRep <$> ff <.> fa) (m <> n)++instance (ComonadApply w, Semigroup (Key g), Representable g) => ComonadApply (StoreT g w) where+ StoreT ff m <@> StoreT fa n = StoreT (apRep <$> ff <@> fa) (m <> n)++instance (Applicative w, Semigroup (Key g), Monoid (Key g), Representable g) => Applicative (StoreT g w) where+ pure a = StoreT (pure (pureRep a)) mempty+ StoreT ff m <*> StoreT fa n = StoreT (apRep <$> ff <*> fa) (m `mappend` n)++instance (Extend w, Representable g) => Extend (StoreT g w) where+ duplicated (StoreT wf s) = StoreT (extended (tabulate . StoreT) wf) s++instance (Comonad w, Representable g) => Comonad (StoreT g w) where+ duplicate (StoreT wf s) = StoreT (extend (tabulate . StoreT) wf) s+ extract (StoreT wf s) = index (extract wf) s++instance Indexable g => ComonadTrans (StoreT g) where+ lower (StoreT w s) = fmap (`index` s) w++instance ComonadHoist (StoreT g) where+ cohoist (StoreT w s) = StoreT (Identity (extract w)) s++instance (ComonadTraced m w, Representable g) => ComonadTraced m (StoreT g w) where+ trace m = trace m . lower++instance (ComonadEnv m w, Representable g) => ComonadEnv m (StoreT g w) where+ ask = ask . lower++instance (Representable g, ComonadCofree f w) => ComonadCofree f (StoreT g w) where+ unwrap (StoreT w s) = fmap (`StoreT` s) (unwrap w)
+ src/Control/Monad/Representable/Reader.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE GADTs, TypeFamilies, TypeOperators, CPP, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, TypeSynonymInstances #-}+{-# OPTIONS_GHC -fenable-rewrite-rules -fno-warn-orphans #-}+----------------------------------------------------------------------+-- |+-- Module : Control.Monad.Representable.Reader+-- Copyright : (c) Edward Kmett 2011,+-- (c) Conal Elliott 2008+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+--+-- Representable functors on Hask all monads, being isomorphic to+-- a reader monad.+----------------------------------------------------------------------++module Control.Monad.Representable.Reader+ (+ -- * Representable functor monad+ Reader, runReader+ -- * Monad Transformer+ , ReaderT(..), readerT, runReaderT+ , ask+ , local+ , module Data.Functor.Representable+ ) where++import Control.Applicative+import Control.Comonad+import Control.Monad.Reader.Class+import Control.Monad.Writer.Class as Writer+import Control.Monad.Trans.Class+import Control.Monad.IO.Class+import Data.Distributive+import Data.Key+import Data.Functor.Bind+import Data.Functor.Extend+import Data.Functor.Identity+import Data.Functor.Representable+import Data.Foldable+import Data.Traversable+import Data.Semigroup+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable+import Prelude hiding (lookup,zipWith)++type Reader f = ReaderT f Identity++runReader :: Indexable f => Reader f b -> Key f -> b+runReader = fmap runIdentity . runReaderT++-- * This 'representable monad transformer' transforms any monad @m@ with a 'Representable' 'Monad'.+-- This monad in turn is also representable if @m@ is 'Representable'.+newtype ReaderT f m b = ReaderT { getReaderT :: f (m b) }++readerT :: Representable f => (Key f -> m b) -> ReaderT f m b+readerT = ReaderT . tabulate++runReaderT :: Indexable f => ReaderT f m b -> Key f -> m b+runReaderT = index . getReaderT++type instance Key (ReaderT f m) = (Key f, Key m)++instance (Functor f, Functor m) => Functor (ReaderT f m) where+ fmap f = ReaderT . fmap (fmap f) . getReaderT++instance (Indexable f, Indexable m) => Indexable (ReaderT f m) where+ index = uncurry . fmap index . index . getReaderT++instance (Representable f, Representable m) => Representable (ReaderT f m) where+ tabulate = ReaderT . tabulate . fmap tabulate . curry++instance (Representable f, Apply m) => Apply (ReaderT f m) where+ ReaderT ff <.> ReaderT fa = ReaderT (unrep ((<.>) <$> Rep ff <.> Rep fa))++instance (Representable f, Applicative m) => Applicative (ReaderT f m) where+ pure = ReaderT . pureRep . pure+ ReaderT ff <*> ReaderT fa = ReaderT (unrep ((<*>) <$> Rep ff <*> Rep fa))++instance (Representable f, Bind m) => Bind (ReaderT f m) where+ ReaderT fm >>- f = ReaderT $ tabulate (\a -> index fm a >>- flip index a . getReaderT . f)++instance (Representable f, Monad m) => Monad (ReaderT f m) where+ return = ReaderT . pureRep . return+ ReaderT fm >>= f = ReaderT $ tabulate (\a -> index fm a >>= flip index a . getReaderT . f)++#if __GLASGOW_HASKELL >= 704++instance (Representable f, Monad m, Key f ~ e) => MonadReader e (ReaderT f m) where+ ask = ReaderT (tabulate return)+ local f m = readerT $ \r -> runReaderT m (f r)+#if MIN_VERSION_transformers(0,3,0)+ reader = readerT . fmap return+#endif++#endif++instance Representable f => MonadTrans (ReaderT f) where+ lift = ReaderT . pureRep++instance (Representable f, Distributive m) => Distributive (ReaderT f m) where+ distribute = ReaderT . fmapRep distribute . unrep . collect (Rep . getReaderT)++instance (Representable f, Keyed m) => Keyed (ReaderT f m) where+ mapWithKey f = ReaderT . mapWithKeyRep (\k -> mapWithKey (f . (,) k)) . getReaderT++instance (Indexable f, Lookup m) => Lookup (ReaderT f m) where+ lookup (k,k') (ReaderT fm) = lookup k' (index fm k)++instance (Representable f, Representable m, Semigroup (Key f), Semigroup (Key m)) => Extend (ReaderT f m) where+ extended = extendedRep+ duplicated = duplicatedRep++instance (Representable f, Zip m) => Zip (ReaderT f m) where+ zipWith f (ReaderT as) (ReaderT bs) = ReaderT $ tabulate $ \i -> zipWith f (index as i) (index bs i)++instance (Representable f, ZipWithKey m) => ZipWithKey (ReaderT f m) where+ zipWithKey f (ReaderT as) (ReaderT bs) = ReaderT $ tabulate $ \i -> zipWithKey (f . (,) i) (index as i) (index bs i)++instance (Representable f, Representable m, Monoid (Key f), Monoid (Key m)) => Comonad (ReaderT f m) where+ extend = extendRep+ duplicate = duplicateRep+ extract = extractRep++instance (Representable f, MonadIO m) => MonadIO (ReaderT f m) where+ liftIO = lift . liftIO++instance (Representable f, MonadWriter w m) => MonadWriter w (ReaderT f m) where+ tell = lift . tell+ listen (ReaderT m) = ReaderT $ tabulate $ Writer.listen . index m+ pass (ReaderT m) = ReaderT $ tabulate $ Writer.pass . index m++-- misc. instances that can exist, but aren't particularly about representability++instance (Adjustable f, Adjustable m) => Adjustable (ReaderT f m) where+ adjust f (kf,km) = ReaderT . adjust (adjust f km) kf . getReaderT++instance (Foldable f, Foldable m) => Foldable (ReaderT f m) where+ foldMap f = foldMap (foldMap f) . getReaderT++instance (Foldable1 f, Foldable1 m) => Foldable1 (ReaderT f m) where+ foldMap1 f = foldMap1 (foldMap1 f) . getReaderT++instance (FoldableWithKey f, FoldableWithKey m) => FoldableWithKey (ReaderT f m) where+ foldMapWithKey f = foldMapWithKey (\k -> foldMapWithKey (f . (,) k)) . getReaderT++instance (FoldableWithKey1 f, FoldableWithKey1 m) => FoldableWithKey1 (ReaderT f m) where+ foldMapWithKey1 f = foldMapWithKey1 (\k -> foldMapWithKey1 (f . (,) k)) . getReaderT++instance (Traversable f, Traversable m) => Traversable (ReaderT f m) where+ traverse f = fmap ReaderT . traverse (traverse f) . getReaderT++instance (Traversable1 f, Traversable1 m) => Traversable1 (ReaderT f m) where+ traverse1 f = fmap ReaderT . traverse1 (traverse1 f) . getReaderT++instance (Representable f, TraversableWithKey f, TraversableWithKey m) => TraversableWithKey (ReaderT f m) where+ traverseWithKey f = fmap ReaderT . traverseWithKey (\k -> traverseWithKey (f . (,) k)) . getReaderT++instance (Representable f, TraversableWithKey1 f, TraversableWithKey1 m) => TraversableWithKey1 (ReaderT f m) where+ traverseWithKey1 f = fmap ReaderT . traverseWithKey1 (\k -> traverseWithKey1 (f . (,) k)) . getReaderT
+ src/Control/Monad/Representable/State.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}+----------------------------------------------------------------------+-- |+-- Module : Control.Monad.Representable.State+-- Copyright : (c) Edward Kmett & Sjoerd Visscher 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+--+-- A generalized State monad, parameterized by a Representable functor.+-- The representation of that functor serves as the state.+----------------------------------------------------------------------+module Control.Monad.Representable.State+ ( State+ , runState+ , evalState+ , execState+ , mapState+ , StateT(..)+ , stateT+ , runStateT+ , evalStateT+ , execStateT+ , mapStateT+ , liftCallCC+ , liftCallCC'+ , get+ , gets+ , put+ , modify+ ) where++import Control.Applicative+import Data.Key+import Data.Functor.Bind+import Data.Functor.Bind.Trans+import Control.Monad.State.Class+import Control.Monad.Cont.Class+import Control.Monad.Reader.Class+import Control.Monad.Writer.Class+import Control.Monad.Free.Class+import Control.Monad.Trans.Class+import Control.Monad.Identity+import Data.Functor.Representable++-- ---------------------------------------------------------------------------+-- | A memoized state monad parameterized by a representable functor @g@, where+-- the representatation of @g@, @Key g@ is the state to carry.+--+-- The 'return' function leaves the state unchanged, while @>>=@ uses+-- the final state of the first computation as the initial state of+-- the second.+type State g = StateT g Identity+++-- | Unwrap a state monad computation as a function.+-- (The inverse of 'state'.)+runState :: Indexable g+ => State g a -- ^ state-passing computation to execute+ -> Key g -- ^ initial state+ -> (a, Key g) -- ^ return value and final state+runState m = runIdentity . runStateT m++-- | Evaluate a state computation with the given initial state+-- and return the final value, discarding the final state.+--+-- * @'evalState' m s = 'fst' ('runState' m s)@+evalState :: Indexable g+ => State g a -- ^state-passing computation to execute+ -> Key g -- ^initial value+ -> a -- ^return value of the state computation+evalState m s = fst (runState m s)++-- | Evaluate a state computation with the given initial state+-- and return the final state, discarding the final value.+--+-- * @'execState' m s = 'snd' ('runState' m s)@+execState :: Indexable g+ => State g a -- ^state-passing computation to execute+ -> Key g -- ^initial value+ -> Key g -- ^final state+execState m s = snd (runState m s)++-- | Map both the return value and final state of a computation using+-- the given function.+--+-- * @'runState' ('mapState' f m) = f . 'runState' m@+mapState :: Functor g => ((a, Key g) -> (b, Key g)) -> State g a -> State g b+mapState f = mapStateT (Identity . f . runIdentity)++-- ---------------------------------------------------------------------------+-- | A state transformer monad parameterized by:+--+-- * @g@ - A representable functor used to memoize results for a state @Key g@+--+-- * @m@ - The inner monad.+--+-- The 'return' function leaves the state unchanged, while @>>=@ uses+-- the final state of the first computation as the initial state of+-- the second.+newtype StateT g m a = StateT { getStateT :: g (m (a, Key g)) }++stateT :: Representable g => (Key g -> m (a, Key g)) -> StateT g m a+stateT = StateT . tabulate++runStateT :: Indexable g => StateT g m a -> Key g -> m (a, Key g)+runStateT (StateT m) = index m++mapStateT :: Functor g => (m (a, Key g) -> n (b, Key g)) -> StateT g m a -> StateT g n b+mapStateT f (StateT m) = StateT (fmap f m)++-- | Evaluate a state computation with the given initial state+-- and return the final value, discarding the final state.+--+-- * @'evalStateT' m s = 'liftM' 'fst' ('runStateT' m s)@+evalStateT :: (Indexable g, Monad m) => StateT g m a -> Key g -> m a+evalStateT m s = do+ (a, _) <- runStateT m s+ return a++-- | Evaluate a state computation with the given initial state+-- and return the final state, discarding the final value.+--+-- * @'execStateT' m s = 'liftM' 'snd' ('runStateT' m s)@+execStateT :: (Indexable g, Monad m) => StateT g m a -> Key g -> m (Key g)+execStateT m s = do+ (_, s') <- runStateT m s+ return s'++instance (Functor g, Functor m) => Functor (StateT g m) where+ fmap f = StateT . fmap (fmap (\ ~(a, s) -> (f a, s))) . getStateT++instance (Functor g, Indexable g, Bind m) => Apply (StateT g m) where+ mf <.> ma = mf >>- \f -> fmap f ma++instance (Representable g, Functor m, Monad m) => Applicative (StateT g m) where+ pure = StateT . leftAdjunctRep return+ mf <*> ma = mf >>= \f -> fmap f ma++instance (Functor g, Indexable g, Bind m) => Bind (StateT g m) where+ StateT m >>- f = StateT $ fmap (>>- rightAdjunctRep (runStateT . f)) m++instance (Representable g, Monad m) => Monad (StateT g m) where+ return = StateT . leftAdjunctRep return+ StateT m >>= f = StateT $ fmap (>>= rightAdjunctRep (runStateT . f)) m++instance Representable f => BindTrans (StateT f) where+ liftB m = stateT $ \s -> fmap (\a -> (a, s)) m++instance Representable f => MonadTrans (StateT f) where+ lift m = stateT $ \s -> liftM (\a -> (a, s)) m++instance (Representable g, Monad m, Key g ~ s) => MonadState s (StateT g m) where+ get = stateT $ \s -> return (s, s)+ put s = StateT $ pureRep $ return ((),s)+#if MIN_VERSION_transformers(0,3,0)+ state f = stateT (return . f)+#endif++-- get :: (Representable g, Monad m) => StateT g m (Key g)+-- put :: (Applicative g, Monad m) => Key g -> StateT g m ()++-- gets :: (Representable g, Monad m) => (Key g -> s) -> StateT g m s+-- gets f = liftM f get++-- modify :: (Representable g, Monad m) => (Key g -> Key g) -> StateT g m ()+-- modify f = stateT $ \s -> return ((), f s)++instance (Representable g, MonadReader e m) => MonadReader e (StateT g m) where+ ask = lift ask+ local = mapStateT . local++instance (Representable g, MonadWriter w m) => MonadWriter w (StateT g m) where+ tell = lift . tell+ listen = mapStateT $ \ma -> do+ ((a,s'), w) <- listen ma+ return ((a,w), s')+ pass = mapStateT $ \ma -> pass $ do+ ((a, f), s') <- ma+ return ((a, s'), f)++instance (Representable g, MonadCont m) => MonadCont (StateT g m) where+ callCC = liftCallCC' callCC++instance (Functor f, Representable g, MonadFree f m) => MonadFree f (StateT g m) where+ wrap as = stateT $ \s -> wrap (fmap (`runStateT` s) as)++leftAdjunctRep :: Representable u => ((a, Key u) -> b) -> a -> u b+leftAdjunctRep f a = tabulate (\s -> f (a,s))++rightAdjunctRep :: Indexable u => (a -> u b) -> (a, Key u) -> b+rightAdjunctRep f ~(a, k) = f a `index` k++-- | Uniform lifting of a @callCC@ operation to the new monad.+-- This version rolls back to the original state on entering the+-- continuation.+liftCallCC :: Representable g => ((((a,Key g) -> m (b,Key g)) -> m (a,Key g)) -> m (a,Key g)) ->+ ((a -> StateT g m b) -> StateT g m a) -> StateT g m a+liftCallCC callCC' f = stateT $ \s ->+ callCC' $ \c ->+ runStateT (f (\a -> StateT $ pureRep $ c (a, s))) s++-- | In-situ lifting of a @callCC@ operation to the new monad.+-- This version uses the current state on entering the continuation.+-- It does not satisfy the laws of a monad transformer.+liftCallCC' :: Representable g => ((((a,Key g) -> m (b,Key g)) -> m (a,Key g)) -> m (a,Key g)) ->+ ((a -> StateT g m b) -> StateT g m a) -> StateT g m a+liftCallCC' callCC' f = stateT $ \s ->+ callCC' $ \c ->+ runStateT (f (\a -> stateT $ \s' -> c (a, s'))) s+
+ src/Data/Functor/Corepresentable.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE TypeFamilies, FlexibleContexts, FlexibleInstances #-}+{-# OPTIONS_GHC -fenable-rewrite-rules #-}++----------------------------------------------------------------------+-- |+-- Module : Data.Functor.Corepresentable+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- +-- Representable contravariant endofunctors over the category of Haskell +-- types are isomorphic to @(_ -> r)@ and resemble mappings to a+-- fixed range.+----------------------------------------------------------------------++module Data.Functor.Corepresentable+ ( + -- * Values+ Value+ -- * Contravariant Keyed+ , Valued(..)+ -- * Contravariant Indexed+ , Coindexed(..)+ -- * Representable Contravariant Functors+ , Corepresentable(..)+ -- * Default definitions+ , contramapDefault+ , contramapWithValueDefault+ ) where++import Control.Monad.Reader+import Data.Functor.Contravariant+import Data.Functor.Product+import Data.Functor.Coproduct+import Prelude hiding (lookup)++type family Value (f :: * -> *)++-- | Dual to 'Keyed'.+class Contravariant f => Valued f where+ contramapWithValue :: (b -> Either a (Value f)) -> f a -> f b++-- | Dual to 'Indexed'.+class Coindexed f where+ coindex :: f a -> a -> Value f++-- | A 'Functor' @f@ is 'Corepresentable' if 'corep' and 'coindex' witness an isomorphism to @(_ -> Value f)@.+--+-- > tabulate . index = id+-- > index . tabulate = id+-- > tabulate . return f = return f++class (Coindexed f, Valued f) => Corepresentable f where+ -- | > contramap f (corep g) = corep (g . f)+ corep :: (a -> Value f) -> f a++{-# RULES+"corep/coindex" forall t. corep (coindex t) = t+ #-}++-- * Default definitions++contramapDefault :: Corepresentable f => (a -> b) -> f b -> f a+contramapDefault f = corep . (. f) . coindex ++contramapWithValueDefault :: Corepresentable f => (b -> Either a (Value f)) -> f a -> f b+contramapWithValueDefault f p = corep $ either (coindex p) id . f++-- * Dual arrows++type instance Value (Op r) = r++instance Valued (Op r) where+ contramapWithValue = contramapWithValueDefault++instance Coindexed (Op r) where+ coindex = getOp++instance Corepresentable (Op r) where+ corep = Op++-- * Predicates++type instance Value Predicate = Bool++instance Valued Predicate where+ contramapWithValue = contramapWithValueDefault++instance Coindexed Predicate where+ coindex = getPredicate++instance Corepresentable Predicate where+ corep = Predicate++-- * Products++type instance Value (Product f g) = (Value f, Value g)++instance (Valued f, Valued g) => Valued (Product f g) where+ -- contramapWithValue :: (b -> Either a (Value f)) -> f a -> f b+ contramapWithValue h (Pair f g) = Pair + (contramapWithValue (fmap fst . h) f)+ (contramapWithValue (fmap snd . h) g)+ -- (contramapWithValue (either id snd . h) g)+ -- (either g snd . h)++instance (Coindexed f, Coindexed g) => Coindexed (Product f g) where+ coindex (Pair f g) a = (coindex f a, coindex g a)++instance (Corepresentable f, Corepresentable g) => Corepresentable (Product f g) where+ corep f = Pair (corep (fst . f)) (corep (snd . f))+++-- * Coproducts++type instance Value (Coproduct f g) = Either (Value f) (Value g)++instance (Coindexed f, Coindexed g) => Coindexed (Coproduct f g) where+ coindex (Coproduct (Left f)) a = Left $ coindex f a + coindex (Coproduct (Right g)) a = Right $ coindex g a
+ src/Data/Functor/Representable.hs view
@@ -0,0 +1,238 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# OPTIONS_GHC -fenable-rewrite-rules #-}+----------------------------------------------------------------------+-- |+-- Module : Data.Functor.Representable+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- +-- Representable endofunctors over the category of Haskell types are +-- isomorphic to the reader monad and so inherit a very large number+-- of properties for free.+----------------------------------------------------------------------++module Data.Functor.Representable+ (+ -- * Representable Functors+ Representable(..)+ -- * Wrapped representable functors+ , Rep(..)+ -- * Default definitions+ -- ** Functor+ , fmapRep+ -- ** Distributive+ , distributeRep+ -- ** Keyed+ , mapWithKeyRep+ -- ** Apply/Applicative+ , apRep+ , pureRep+ , liftR2+ , liftR3+ -- ** Bind/Monad+ , bindRep+ , bindWithKeyRep+ -- ** Zip/ZipWithKey+ , zipWithRep+ , zipWithKeyRep+ -- ** MonadReader+ , askRep+ , localRep+ -- ** Extend+ , duplicatedRep+ , extendedRep+ -- ** Comonad+ , duplicateRep+ , extendRep+ , extractRep+ ) where++import Control.Applicative+import Control.Comonad+import Control.Comonad.Trans.Class+import Control.Comonad.Trans.Traced+import Control.Comonad.Cofree+import Control.Monad.Trans.Identity+import Control.Monad.Reader+import Data.Distributive+import Data.Key+import Data.Functor.Bind+import Data.Functor.Identity+import Data.Functor.Compose+import Data.Functor.Extend+import Data.Functor.Product+import qualified Data.Sequence as Seq+import Data.Semigroup hiding (Product)+import Prelude hiding (lookup)++-- | A 'Functor' @f@ is 'Representable' if 'tabulate' and 'index' witness an isomorphism to @(->) x@.+--+-- > tabulate . index = id+-- > index . tabulate = id+-- > tabulate . return f = return f++class (Functor f, Indexable f) => Representable f where+ -- | > fmap f . tabulate = tabulate . fmap f+ tabulate :: (Key f -> a) -> f a++{-# RULES+"tabulate/index" forall t. tabulate (index t) = t+ #-}++-- * Default definitions++fmapRep :: Representable f => (a -> b) -> f a -> f b+fmapRep f = tabulate . fmap f . index++mapWithKeyRep :: Representable f => (Key f -> a -> b) -> f a -> f b+mapWithKeyRep f = tabulate . (<*>) f . index++pureRep :: Representable f => a -> f a+pureRep = tabulate . const++bindRep :: Representable f => f a -> (a -> f b) -> f b+bindRep m f = tabulate (\a -> index (f (index m a)) a)++bindWithKeyRep :: Representable f => f a -> (Key f -> a -> f b) -> f b+bindWithKeyRep m f = tabulate (\a -> index (f a (index m a)) a)++askRep :: Representable f => f (Key f)+askRep = tabulate id++localRep :: Representable f => (Key f -> Key f) -> f a -> f a+localRep f m = tabulate (index m . f)++apRep :: Representable f => f (a -> b) -> f a -> f b+apRep f g = tabulate (index f <*> index g)++zipWithRep :: Representable f => (a -> b -> c) -> f a -> f b -> f c+zipWithRep f g h = tabulate $ \k -> f (index g k) (index h k)++zipWithKeyRep :: Representable f => (Key f -> a -> b -> c) -> f a -> f b -> f c+zipWithKeyRep f g h = tabulate $ \k -> f k (index g k) (index h k)++distributeRep :: (Representable f, Functor w) => w (f a) -> f (w a)+distributeRep wf = tabulate (\k -> fmap (`index` k) wf)++duplicatedRep :: (Representable f, Semigroup (Key f)) => f a -> f (f a)+duplicatedRep w = tabulate (\m -> tabulate (index w . (<>) m))++extendedRep :: (Representable f, Semigroup (Key f)) => (f a -> b) -> f a -> f b+extendedRep f w = tabulate (\m -> f (tabulate (index w . (<>) m)))++duplicateRep :: (Representable f, Monoid (Key f)) => f a -> f (f a)+duplicateRep w = tabulate (\m -> tabulate (index w . mappend m))++extendRep :: (Representable f, Monoid (Key f)) => (f a -> b) -> f a -> f b+extendRep f w = tabulate (\m -> f (tabulate (index w . mappend m)))++extractRep :: (Indexable f, Monoid (Key f)) => f a -> a+extractRep fa = index fa mempty++{-+-- | We extend lens across a representable functor, due to the preservation of limits.+repLens :: Representable f => Lens a b -> Lens (f a) (f b)+repLens l = lens (fmapRep (l ^$)) $ \a b -> unrep $ liftA2 (l ^=) (Rep a) (Rep b)+-}++-- representing :: (Representable f, Functor g) => ((c -> g d) -> a -> g b) -> (f c -> g (f d)) -> f a -> g (f b)++-- * Instances++instance Representable Identity where+ tabulate f = Identity (f ())++instance Representable m => Representable (IdentityT m) where+ tabulate = IdentityT . tabulate++instance Representable ((->) e) where+ tabulate = id++instance Representable m => Representable (ReaderT e m) where+ tabulate = ReaderT . fmap tabulate . curry ++instance (Representable f, Representable g) => Representable (Compose f g) where+ tabulate = Compose . tabulate . fmap tabulate . curry++instance Representable w => Representable (TracedT s w) where+ -- tabulate = TracedT . collect tabulate . curry+ tabulate = TracedT . unrep . collect (Rep . tabulate) . curry++instance (Representable f, Representable g) => Representable (Product f g) where+ tabulate f = Pair (tabulate (f . Left)) (tabulate (f . Right))++instance Representable f => Representable (Cofree f) where+ tabulate f = f Seq.empty :< tabulate (\k -> tabulate (f . (k Seq.<|)))+++newtype Rep f a = Rep { unrep :: f a }++type instance Key (Rep f) = Key f++instance Representable f => Representable (Rep f) where+ tabulate = Rep . tabulate++instance Indexable f => Indexable (Rep f) where+ index (Rep f) i = index f i++instance Representable f => Keyed (Rep f) where+ mapWithKey = mapWithKeyRep++instance Indexable f => Lookup (Rep f) where+ lookup = lookupDefault++instance Representable f => Functor (Rep f) where+ fmap = fmapRep++instance Representable f => Apply (Rep f) where+ (<.>) = apRep++instance Representable f => Applicative (Rep f) where+ pure = pureRep+ (<*>) = apRep++instance Representable f => Distributive (Rep f) where+ distribute = distributeRep++instance Representable f => Bind (Rep f) where+ (>>-) = bindRep++instance Representable f => Monad (Rep f) where+ return = pureRep+ (>>=) = bindRep++#if __GLASGOW_HASKELL__ >= 704+instance (Representable f, Key f ~ a) => MonadReader a (Rep f) where+ ask = askRep+ local = localRep+#endif++instance Representable f => Zip (Rep f) where+ zipWith = zipWithRep++instance Representable f => ZipWithKey (Rep f) where+ zipWithKey = zipWithKeyRep++instance (Representable f, Semigroup (Key f)) => Extend (Rep f) where+ extended = extendedRep++instance (Representable f, Monoid (Key f)) => Comonad (Rep f) where+ extend = extendRep+ extract = extractRep++instance ComonadTrans Rep where+ lower (Rep f) = f++liftR2 :: Representable f => (a -> b -> c) -> f a -> f b -> f c+liftR2 f fa fb = tabulate $ \i -> f (index fa i) (index fb i)++liftR3 :: Representable f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d+liftR3 f fa fb fc = tabulate $ \i -> f (index fa i) (index fb i) (index fc i)