{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DeriveDataTypeable #-} #ifndef MIN_VERSION_MTL #define MIN_VERSION_MTL(x,y,z) 1 #endif ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.Trans.Iter -- Copyright : (C) 2013 Edward Kmett -- License : BSD-style (see the file LICENSE) -- -- Maintainer : Edward Kmett -- Stability : provisional -- Portability : MPTCs, fundeps -- -- Based on -- -- Unlike 'Free', this is a true monad transformer. ---------------------------------------------------------------------------- module Control.Monad.Trans.Iter ( MonadFree(..) , IterF(..) , IterT(..) , delay , retract , iter , hoistIterT ) where import Control.Applicative import Control.Monad (ap, liftM, MonadPlus(..)) import Control.Monad.Fix import Control.Monad.Trans.Class import Control.Monad.Free.Class import Control.Monad.State.Class import Control.Monad.Reader.Class import Data.Bifoldable import Data.Bifunctor import Data.Bitraversable import Data.Functor.Bind import Data.Functor.Identity import Data.Foldable import Data.Monoid import Data.Traversable import Data.Semigroup.Foldable import Data.Semigroup.Traversable import Data.Typeable #ifdef GHC_TYPEABLE import Data.Data #endif data IterF a b = Pure a | Iter b deriving (Eq,Ord,Show,Read,Typeable) instance Functor (IterF a) where fmap _ (Pure a) = Pure a fmap f (Iter b) = Iter (f b) instance Foldable (IterF a) where foldMap f (Iter b) = f b foldMap _ _ = mempty instance Traversable (IterF a) where traverse _ (Pure a) = pure (Pure a) traverse f (Iter b) = Iter <$> f b instance Bifunctor IterF where bimap f _ (Pure a) = Pure (f a) bimap _ g (Iter b) = Iter (g b) instance Bifoldable IterF where bifoldMap f _ (Pure a) = f a bifoldMap _ g (Iter b) = g b instance Bitraversable IterF where bitraverse f _ (Pure a) = Pure <$> f a bitraverse _ g (Iter b) = Iter <$> g b iterF :: (a -> r) -> (b -> r) -> IterF a b -> r iterF f _ (Pure a) = f a iterF _ g (Iter b) = g b {-# INLINE iterF #-} -- | The monad supporting iteration based over a base monad @m@. -- -- @ -- 'IterT' ~ 'FreeT' 'Identity' -- @ data IterT m a = IterT { runIterT :: m (IterF a (IterT m a)) } #if __GLASGOW_HASKELL__ >= 707 deriving (Typeable) #endif instance Eq (m (IterF a (IterT m a))) => Eq (IterT m a) where IterT m == IterT n = m == n instance Ord (m (IterF a (IterT m a))) => Ord (IterT m a) where compare (IterT m) (IterT n) = compare m n instance Show (m (IterF a (IterT m a))) => Show (IterT m a) where showsPrec d (IterT m) = showParen (d > 10) $ showString "IterT " . showsPrec 11 m instance Read (m (IterF a (IterT m a))) => Read (IterT m a) where readsPrec d = readParen (d > 10) $ \r -> [ (IterT m,t) | ("IterT",s) <- lex r, (m,t) <- readsPrec 11 s] instance Monad m => Functor (IterT m) where fmap f = IterT . liftM (bimap f (fmap f)) . runIterT {-# INLINE fmap #-} instance Monad m => Applicative (IterT m) where pure = IterT . return . Pure {-# INLINE pure #-} (<*>) = ap {-# INLINE (<*>) #-} instance Monad m => Monad (IterT m) where return = IterT . return . Pure {-# INLINE return #-} IterT m >>= k = IterT $ m >>= iterF (runIterT . k) (return . Iter . (>>= k)) {-# INLINE (>>=) #-} fail = IterT . fail {-# INLINE fail #-} instance Monad m => Apply (IterT m) where (<.>) = ap {-# INLINE (<.>) #-} instance Monad m => Bind (IterT m) where (>>-) = (>>=) {-# INLINE (>>-) #-} instance MonadFix m => MonadFix (IterT m) where mfix f = IterT $ mfix (runIterT . f . unPure) where unPure (Pure x) = x unPure (Iter _) = error "mfix (IterT m): Iter" {-# INLINE mfix #-} instance MonadPlus m => Alternative (IterT m) where empty = IterT mzero {-# INLINE empty #-} IterT a <|> IterT b = IterT (mplus a b) {-# INLINE (<|>) #-} instance MonadPlus m => MonadPlus (IterT m) where mzero = IterT mzero {-# INLINE mzero #-} IterT a `mplus` IterT b = IterT (mplus a b) {-# INLINE mplus #-} -- | This is not a true monad transformer. It is only a monad transformer \"up to 'retract'\". instance MonadTrans IterT where lift = IterT . liftM Pure {-# INLINE lift #-} instance Foldable m => Foldable (IterT m) where foldMap f = foldMap (iterF f (foldMap f)) . runIterT {-# INLINE foldMap #-} instance Foldable1 m => Foldable1 (IterT m) where foldMap1 f = foldMap1 (iterF f (foldMap1 f)) . runIterT {-# INLINE foldMap1 #-} instance (Monad m, Traversable m) => Traversable (IterT m) where traverse f (IterT m) = IterT <$> traverse (bitraverse f (traverse f)) m {-# INLINE traverse #-} instance (Monad m, Traversable1 m) => Traversable1 (IterT m) where traverse1 f (IterT m) = IterT <$> traverse1 go m where go (Pure a) = Pure <$> f a go (Iter a) = Iter <$> traverse1 f a {-# INLINE traverse1 #-} {- instance MonadWriter e m => MonadWriter e (IterT m) where tell = lift . tell {-# INLINE tell #-} listen = lift . listen . retract {-# INLINE listen #-} pass = lift . pass . retract {-# INLINE pass #-} -} instance (Functor m, MonadReader e m) => MonadReader e (IterT m) where ask = lift ask {-# INLINE ask #-} local f = hoistIterT (local f) {-# INLINE local #-} instance (Functor m, MonadState s m) => MonadState s (IterT m) where get = lift get {-# INLINE get #-} put s = lift (put s) {-# INLINE put #-} #if MIN_VERSION_mtl(2,1,1) state f = lift (state f) {-# INLINE state #-} #endif {- instance (Functor m, MonadError e m) => MonadError e (Free m) where throwError = lift . throwError {-# INLINE throwError #-} catchError as f = lift (catchError (retract as) (retract . f)) {-# INLINE catchError #-} instance (Functor m, MonadCont m) => MonadCont (Free m) where callCC f = lift (callCC (retract . f . liftM lift)) {-# INLINE callCC #-} -} instance Monad m => MonadFree Identity (IterT m) where wrap = IterT . return . Iter . runIdentity {-# INLINE wrap #-} delay :: (Monad f, MonadFree f m) => m a -> m a delay = wrap . return {-# INLINE delay #-} -- | -- 'retract' is the left inverse of 'lift' -- -- @ -- 'retract' . 'lift' = 'id' -- @ retract :: Monad m => IterT m a -> m a retract m = runIterT m >>= iterF return retract -- | Tear down a 'Free' 'Monad' using iteration. iter :: Monad m => (m a -> a) -> IterT m a -> a iter phi (IterT m) = phi (iterF id (iter phi) `liftM` m) -- | Lift a monad homomorphism from @m@ to @n@ into a Monad homomorphism from @'IterT' m@ to @'IterT' n@. hoistIterT :: Monad n => (forall a. m a -> n a) -> IterT m b -> IterT n b hoistIterT f (IterT as) = IterT (fmap (hoistIterT f) `liftM` f as) #if defined(GHC_TYPEABLE) && __GLASGOW_HASKELL__ < 707 instance Typeable1 m => Typeable1 (IterT m) where typeOf1 t = mkTyConApp freeTyCon [typeOf1 (f t)] where f :: IterT m a -> m a f = undefined freeTyCon :: TyCon #if __GLASGOW_HASKELL__ < 704 freeTyCon = mkTyCon "Control.Monad.Iter.IterT" #else freeTyCon = mkTyCon3 "free" "Control.Monad.Iter" "IterT" #endif {-# NOINLINE freeTyCon #-} instance ( Typeable1 m, Typeable a , Data (m (IterF a (IterT m a))) , Data a ) => Data (IterT m a) where gfoldl f z (IterT as) = z IterT `f` as toConstr IterT{} = iterConstr gunfold k z c = case constrIndex c of 1 -> k (z IterT) _ -> error "gunfold" dataTypeOf _ = iterDataType dataCast1 f = gcast1 f iterConstr :: Constr iterConstr = mkConstr iterDataType "IterT" [] Prefix {-# NOINLINE iterConstr #-} iterDataType :: DataType iterDataType = mkDataType "Control.Monad.Iter.IterT" [iterConstr] {-# NOINLINE iterDataType #-} #endif