module FP.Prelude.Monads where import FP.Prelude.Core import FP.Prelude.Effects import FP.Prelude.Constraints import FP.Prelude.Morphism import FP.Prelude.Lattice -- E and I effects can be implemented by combining unit, discard and commute -- All effects are implemented this way except for continuation effects class FunctorUnit (t ∷ (★ → ★) → (★ → ★)) where funit ∷ (Functor m) ⇒ m ↝ t m class FunctorDiscard (t ∷ (★ → ★) → (★ → ★)) where fdiscard ∷ (Functor m) ⇒ t (t m) ↝ t m -- For commuting effects class FunctorFunctor (t ∷ (★ → ★) → (★ → ★)) where fmap ∷ m ↝ n → t m ↝ t n class FunctorIsoFunctor (t ∷ (★ → ★) → (★ → ★)) where fisomap ∷ (m ↝ n,n ↝ m) → (t m ↝ t n) -- # ID newtype ID a = ID { runID ∷ a } deriving ( Eq,Ord , POrd,Bot,Join,Meet,Top,JoinLattice,Monoid,Difference ) isoID ∷ ID a ⇄ a isoID = Iso runID ID instance Functor ID where map ∷ (a → b) → ID a → ID b map f = ID ∘ f ∘ runID instance FunctorM ID where mapM ∷ (Monad m) ⇒ (a → m b) → ID a → m (ID b) mapM f = map ID ∘ f ∘ runID instance Monad ID where return ∷ a → ID a return = ID (≫=) ∷ ID a → (a → ID b) → ID b aM ≫= k = k $ runID aM instance Functorial POrd ID where functorial = W instance OrdFunctorial POrd ID where ordFunctorial = W instance Functorial Bot ID where functorial = W instance Functorial Join ID where functorial = W instance Functorial Meet ID where functorial = W instance Functorial Top ID where functorial = W instance Functorial JoinLattice ID where functorial = W instance Functorial Monoid ID where functorial = W -- # Failure -- Base Effect type Failure = FailureT ID failure ∷ Maybe a → Failure a failure = abortMaybe runFailure ∷ Failure a → Maybe a runFailure = runID ∘ runFailureT -- Commuting with self commuteFailure ∷ (Functor m) ⇒ FailureT (FailureT m) ↝ FailureT (FailureT m) commuteFailure aMM = FailureT $ FailureT $ ff ^$ runFailureT $ runFailureT aMM where ff ∷ Maybe (Maybe a) → Maybe (Maybe a) ff Nothing = Just Nothing ff (Just Nothing) = Nothing ff (Just (Just a)) = Just (Just a) -- Functor and Monad instance (Functor m) ⇒ Functor (FailureT m) where map ∷ (a → b) → FailureT m a → FailureT m b map f = FailureT ∘ map (map f) ∘ runFailureT instance (Monad m) ⇒ Monad (FailureT m) where return ∷ a → FailureT m a return = FailureT ∘ return ∘ Just (≫=) ∷ FailureT m a → (a → FailureT m b) → FailureT m b aM ≫= k = FailureT $ do aM' ← runFailureT aM case aM' of Nothing → return Nothing Just a → runFailureT $ k a -- Higher Functor instance FunctorUnit FailureT where funit ∷ (Functor m) ⇒ m ↝ FailureT m funit = FailureT ∘ map Just instance FunctorDiscard FailureT where fdiscard ∷ (Functor m) ⇒ FailureT (FailureT m) ↝ FailureT m fdiscard = FailureT ∘ ff ^∘ runFailureT ∘ runFailureT where ff ∷ Maybe (Maybe a) → Maybe a ff Nothing = Nothing ff (Just aM) = aM instance FunctorFunctor FailureT where fmap ∷ (m ↝ n) → FailureT m ↝ FailureT n fmap f = FailureT ∘ f ∘ runFailureT -- MonadMonoid and MonadJoin instance (MonadMonoid m) ⇒ MonadMonoid (FailureT m) where mnull ∷ FailureT m a mnull = FailureT mnull (<⧺>) ∷ FailureT m a → FailureT m a → FailureT m a aM₁ <⧺> aM₂ = FailureT $ runFailureT aM₁ <⧺> runFailureT aM₂ instance (MonadBot m) ⇒ MonadBot (FailureT m) where mbot ∷ FailureT m a mbot = FailureT mbot instance (MonadJoin m) ⇒ MonadJoin (FailureT m) where (<⊔>) ∷ FailureT m a → FailureT m a → FailureT m a aM₁ <⊔> aM₂ = FailureT $ runFailureT aM₁ <⊔> runFailureT aM₂ instance (MonadJoinLattice m) ⇒ MonadJoinLattice (FailureT m) -- Failure Effect instance (Functor m) ⇒ MonadFailure (FailureT m) where failureE ∷ FailureT (FailureT m) ↝ FailureT m failureE = fdiscard ∘ commuteFailure failureI ∷ FailureT m ↝ FailureT (FailureT m) failureI = commuteFailure ∘ funit -- Maybe Failure Effect instance MonadFailure Maybe where failureE ∷ FailureT Maybe ↝ Maybe failureE = runFailure ∘ failureE ∘ fmap failure failureI ∷ Maybe ↝ FailureT Maybe failureI = fmap runFailure ∘ failureI ∘ failure -- # Error -- Base Effect type Error e = ErrorT e ID runError ∷ Error e a → e ⨄ a runError = runID ∘ runErrorT -- Commuting with self errorCommute ∷ (Functor m) ⇒ ErrorT e (ErrorT e m) ↝ ErrorT e (ErrorT e m) errorCommute = ErrorT ∘ ErrorT ∘ ff ^∘ runErrorT ∘ runErrorT where ff ∷ e ⨄ (e ⨄ a) → e ⨄ (e ⨄ a) ff (Left e) = Right (Left e) ff (Right (Left e)) = Left e ff (Right (Right a)) = Right $ Right a -- Functor and Monad instance (Functor m) ⇒ Functor (ErrorT e m) where map ∷ (a → b) → ErrorT e m a → ErrorT e m b map f aM = ErrorT $ mapRight f ^$ runErrorT aM instance (Monad m) ⇒ Monad (ErrorT e m) where return ∷ a → ErrorT e m a return = ErrorT ∘ return ∘ Right (≫=) ∷ ErrorT e m a → (a → ErrorT e m b) → ErrorT e m b aM ≫= k = ErrorT $ do aeM ← runErrorT aM case aeM of Left e → return $ Left e Right a → runErrorT $ k a -- Higher Functor instance FunctorUnit (ErrorT e) where funit ∷ (Functor m) ⇒ m ↝ ErrorT e m funit aM = ErrorT $ Right ^$ aM instance FunctorDiscard (ErrorT e) where fdiscard ∷ (Functor m) ⇒ ErrorT e (ErrorT e m) ↝ ErrorT e m fdiscard = ErrorT ∘ ff ^∘ runErrorT ∘ runErrorT where ff (Left e) = Left e ff (Right ea) = ea instance FunctorFunctor (ErrorT e) where fmap ∷ m ↝ n → ErrorT e m ↝ ErrorT e n fmap f = ErrorT ∘ f ∘ runErrorT -- MonadMonoid and MonadJoin instance (MonadMonoid m) ⇒ MonadMonoid (ErrorT e m) where mnull ∷ ErrorT e m a mnull = ErrorT mnull (<⧺>) ∷ ErrorT e m a → ErrorT e m a → ErrorT e m a aM₁ <⧺> aM₂ = ErrorT $ runErrorT aM₁ <⧺> runErrorT aM₂ instance (MonadBot m) ⇒ MonadBot (ErrorT e m) where mbot ∷ ErrorT e m a mbot = ErrorT mbot instance (MonadJoin m) ⇒ MonadJoin (ErrorT e m) where (<⊔>) ∷ ErrorT e m a → ErrorT e m a → ErrorT e m a aM₁ <⊔> aM₂ = ErrorT $ runErrorT aM₁ <⊔> runErrorT aM₂ -- Error Effect instance (Functor m) ⇒ MonadError e (ErrorT e m) where errorE ∷ ErrorT e (ErrorT e m) ↝ ErrorT e m errorE = fdiscard ∘ errorCommute errorI ∷ ErrorT e m ↝ ErrorT e (ErrorT e m) errorI = errorCommute ∘ funit -- Sum Error Effect instance MonadError e ((⨄) e) where errorE ∷ ErrorT e ((⨄) e) ↝ (⨄) e errorE = runError ∘ errorE ∘ fmap throwSum errorI ∷ (⨄) e ↝ ErrorT e ((⨄) e) errorI = fmap runError ∘ errorI ∘ throwSum -- # Reader -- Base Effect type Reader r = ReaderT r ID reader ∷ (r → a) → Reader r a reader f = ReaderT $ ID ∘ f runReader ∷ Reader r a → r → a runReader = runID ∘∘ runReaderT runReaderWith ∷ r → Reader r a → a runReaderWith = flip runReader -- Commuting with self readerCommute ∷ ReaderT r₁ (ReaderT r₂ m) ↝ ReaderT r₂ (ReaderT r₁ m) readerCommute aMM = ReaderT $ \ r₂ → ReaderT $ \ r₁ → runReaderTWith r₂ $ runReaderTWith r₁ aMM -- Functor and Monad instance (Functor m) ⇒ Functor (ReaderT r m) where map ∷ (a → b) → ReaderT r m a → ReaderT r m b map f aM = ReaderT $ map f ∘ runReaderT aM instance (Monad m) ⇒ Monad (ReaderT r m) where return ∷ a → ReaderT r m a return = ReaderT ∘ const ∘ return (≫=) ∷ ReaderT r m a → (a → ReaderT r m b) → ReaderT r m b aM ≫= k = ReaderT $ \ r → runReaderTWith r ∘ k *$ runReaderTWith r aM -- Higher Functor instance FunctorUnit (ReaderT r) where funit ∷ (Functor m) ⇒ m ↝ ReaderT r m funit = ReaderT ∘ const instance FunctorDiscard (ReaderT r) where fdiscard ∷ (Functor m) ⇒ ReaderT r (ReaderT r m) ↝ ReaderT r m fdiscard aMM = ReaderT $ \ r → runReaderTWith r $ runReaderTWith r aMM instance FunctorFunctor (ReaderT r) where fmap ∷ (m ↝ n) → (ReaderT r m ↝ ReaderT r n) fmap f aM = ReaderT $ \ r → f $ runReaderTWith r aM -- MonadMonoid and Join instance (MonadMonoid m) ⇒ MonadMonoid (ReaderT r m) where mnull ∷ ReaderT r m a mnull = ReaderT $ const mnull (<⧺>) ∷ ReaderT r m a → ReaderT r m a → ReaderT r m a aM₁ <⧺> aM₂ = ReaderT $ \ r → runReaderT aM₁ r <⧺> runReaderT aM₂ r instance (MonadBot m) ⇒ MonadBot (ReaderT r m) where mbot ∷ ReaderT r m a mbot = ReaderT $ const mbot instance (MonadJoin m) ⇒ MonadJoin (ReaderT r m) where (<⊔>) ∷ ReaderT r m a → ReaderT r m a → ReaderT r m a aM₁ <⊔> aM₂ = ReaderT $ \ r → runReaderT aM₁ r <⊔> runReaderT aM₂ r instance (MonadJoinLattice m) ⇒ MonadJoinLattice (ReaderT r m) -- Reader Effect instance (Functor m) ⇒ MonadReader r (ReaderT r m) where readerE ∷ ReaderT r (ReaderT r m) ↝ ReaderT r m readerE = fdiscard ∘ readerCommute readerI ∷ ReaderT r m ↝ ReaderT r (ReaderT r m) readerI = readerCommute ∘ funit -- Base Reader Effect instance MonadReader r ((→) r) where readerE ∷ ReaderT r ((→) r) ↝ (→) r readerE = runReader ∘ readerE ∘ fmap reader readerI ∷ (→) r ↝ ReaderT r ((→) r) readerI = fmap runReader ∘ readerI ∘ reader -- # Writer -- Base Effect type Writer o = WriterT o ID writer ∷ (a,o) → Writer o a writer = WriterT ∘ ID runWriter ∷ Writer o a → (a,o) runWriter = runID ∘ runWriterT execWriter ∷ Writer o a → o execWriter = snd ∘ runWriter -- Commuting with self writerCommute ∷ ∀ m o₁ o₂. (Functor m) ⇒ WriterT o₁ (WriterT o₂ m) ↝ WriterT o₂ (WriterT o₁ m) writerCommute aMM = WriterT $ WriterT $ ff ^$ runWriterT $ runWriterT aMM where ff ∷ ((a,o₁),o₂) → ((a,o₂),o₁) ff ((a,o₁),o₂) = ((a,o₂),o₁) -- Functor and Monad instance (Functor m) ⇒ Functor (WriterT o m) where map ∷ (a → b) → WriterT o m a → WriterT o m b map f = WriterT ∘ mapFst f ^∘ runWriterT instance (Monad m,Monoid o) ⇒ Monad (WriterT o m) where return ∷ a → WriterT o m a return = WriterT ∘ return ∘ (,null) (≫=) ∷ WriterT o m a → (a → WriterT o m b) → WriterT o m b aM ≫= k = WriterT $ do (a,o₁) ← runWriterT aM (b,o₂) ← runWriterT $ k a o' ← return ♯$ o₁ ⧺ o₂ return (b,o') -- Higher Functor instance (Monoid o) ⇒ FunctorUnit (WriterT o) where funit ∷ (Functor m) ⇒ m ↝ WriterT o m funit = WriterT ∘ map (,null) instance FunctorDiscard (WriterT o) where fdiscard ∷ (Functor m) ⇒ WriterT o (WriterT o m) ↝ WriterT o m fdiscard = fst ^∘ runWriterT instance FunctorFunctor (WriterT o) where fmap ∷ (m ↝ n) → (WriterT o m ↝ WriterT o n) fmap f aM = WriterT $ f $ runWriterT aM -- MonadMonoid and MonadJoin instance (MonadMonoid m,Monoid o) ⇒ MonadMonoid (WriterT o m) where mnull ∷ WriterT o m a mnull = WriterT mnull (<⧺>) ∷ WriterT o m a → WriterT o m a → WriterT o m a aM₁ <⧺> aM₂ = WriterT $ runWriterT aM₁ <⧺> runWriterT aM₂ instance (MonadBot m,Monoid o) ⇒ MonadBot (WriterT o m) where mbot ∷ WriterT o m a mbot = WriterT mbot instance (MonadJoin m,Monoid o) ⇒ MonadJoin (WriterT o m) where (<⊔>) ∷ WriterT o m a → WriterT o m a → WriterT o m a aM₁ <⊔> aM₂ = WriterT $ runWriterT aM₁ <⊔> runWriterT aM₂ instance (MonadJoinLattice m,Monoid o) ⇒ MonadJoinLattice (WriterT o m) -- Monoid Functor instance (Functorial Monoid m,Monoid o,Monoid a) ⇒ Monoid (WriterT o m a) where null ∷ WriterT o m a null = with (functorial ∷ W (Monoid (m (a,o)))) $ WriterT null (⧺) ∷ WriterT o m a → WriterT o m a → WriterT o m a aM₁ ⧺ aM₂ = with (functorial ∷ W (Monoid (m (a,o)))) $ WriterT $ runWriterT aM₁ ⧺ runWriterT aM₂ instance (Functorial Monoid m,Monoid o) ⇒ Functorial Monoid (WriterT o m) where functorial = W -- Writer Effect instance (Functor m,Monoid o) ⇒ MonadWriter o (WriterT o m) where writerE ∷ WriterT o (WriterT o m) ↝ WriterT o m writerE = fdiscard ∘ writerCommute writerI ∷ WriterT o m ↝ WriterT o (WriterT o m) writerI = writerCommute ∘ funit -- Base Writer Effect instance (Monoid o) ⇒ MonadWriter o ((,) o) where writerE ∷ WriterT o ((,) o) ↝ ((,) o) writerE = swap ∘ runWriter ∘ writerE ∘ fmap (writer ∘ swap) writerI ∷ ((,) o) ↝ WriterT o ((,) o) writerI = fmap (swap ∘ runWriter) ∘ writerI ∘ writer ∘ swap -- # State -- Base Effect type State s = StateT s ID runStateWith ∷ s → State s a → (a,s) runStateWith = runID ∘∘ runStateTWith evalStateWith ∷ s → State s a → a evalStateWith = fst ∘∘ runStateWith execStateWith ∷ s → State s a → s execStateWith = snd ∘∘ runStateWith -- Commuting with self stateCommute ∷ ∀ m s₁ s₂. (Functor m) ⇒ StateT s₁ (StateT s₂ m) ↝ StateT s₂ (StateT s₁ m) stateCommute aMM = StateT $ \ s₂ → StateT $ \ s₁ → ff ^$ runStateTWith s₂ $ runStateTWith s₁ aMM where ff ∷ ((a,s₁),s₂) → ((a,s₂),s₁) ff ((a,s₁),s₂) = ((a,s₂),s₁) -- Functor and Monad instance (Functor m) ⇒ Functor (StateT s m) where map ∷ (a → b) → StateT s m a → StateT s m b map f aM = StateT $ \ s → mapFst f ^$ runStateT aM s instance (Monad m) ⇒ Monad (StateT s m) where return ∷ a → StateT s m a return x = StateT $ \ s → return (x,s) (≫=) ∷ StateT s m a → (a → StateT s m b) → StateT s m b aM ≫= k = StateT $ \ s → do (a,s') ← runStateT aM s runStateT (k a) s' -- Higher Functor instance FunctorUnit (StateT s) where funit ∷ (Functor m) ⇒ m ↝ StateT s m funit aM = StateT $ \ s → (,s) ^$ aM instance FunctorDiscard (StateT s) where fdiscard ∷ (Functor m) ⇒ StateT s (StateT s m) ↝ StateT s m fdiscard aMM = StateT $ \ s → runStateTWith s $ fst ^$ runStateTWith s aMM instance FunctorFunctor (StateT s) where fmap ∷ (m ↝ n) → StateT s m ↝ StateT s n fmap f aM = StateT $ f ∘ runStateT aM -- MonadMonoid and MonadJoin instance (MonadMonoid m) ⇒ MonadMonoid (StateT s m) where mnull ∷ StateT s m a mnull = StateT $ const mnull (<⧺>) ∷ StateT s m a → StateT s m a → StateT s m a aM₁ <⧺> aM₂ = StateT $ \ s → runStateT aM₁ s <⧺> runStateT aM₂ s instance (MonadBot m) ⇒ MonadBot (StateT s m) where mbot ∷ StateT s m a mbot = StateT $ const mbot instance (MonadJoin m) ⇒ MonadJoin (StateT s m) where (<⊔>) ∷ StateT s m a → StateT s m a → StateT s m a aM₁ <⊔> aM₂ = StateT $ \ s → runStateT aM₁ s <⊔> runStateT aM₂ s instance (MonadJoinLattice m) ⇒ MonadJoinLattice (StateT s m) instance (MonadTop m) ⇒ MonadTop (StateT s m) where mtop ∷ StateT s m a mtop = StateT $ const mtop -- Monoid Functor instance (Functorial Monoid m,Monoid s,Monoid a) ⇒ Monoid (StateT s m a) where null ∷ StateT s m a null = with (functorial ∷ W (Monoid (m (a,s)))) $ StateT $ \ _ → null (⧺) ∷ StateT s m a → StateT s m a → StateT s m a aM₁ ⧺ aM₂ = with (functorial ∷ W (Monoid (m (a,s)))) $ StateT $ \ s → runStateT aM₁ s ⧺ runStateT aM₂ s instance (Functorial Monoid m,Monoid s) ⇒ Functorial Monoid (StateT s m) where functorial = W -- JoinLattice Functor instance (Functorial JoinLattice m,JoinLattice s,JoinLattice a) ⇒ Bot (StateT s m a) where bot ∷ StateT s m a bot = with (functorial ∷ W (JoinLattice (m (a,s)))) $ StateT $ \ _ → bot instance (Functorial JoinLattice m,JoinLattice s,JoinLattice a) ⇒ Join (StateT s m a) where (⊔) ∷ StateT s m a → StateT s m a → StateT s m a aM₁ ⊔ aM₂ = with (functorial ∷ W (JoinLattice (m (a,s)))) $ StateT $ \ s → runStateT aM₁ s ⊔ runStateT aM₂ s instance (Functorial JoinLattice m,JoinLattice s,JoinLattice a) ⇒ JoinLattice (StateT s m a) instance (Functorial JoinLattice m,JoinLattice s) ⇒ Functorial JoinLattice (StateT s m) where functorial = W -- State Effect instance (Functor m) ⇒ MonadState s (StateT s m) where stateE ∷ StateT s (StateT s m) ↝ StateT s m stateE = fdiscard ∘ stateCommute stateI ∷ StateT s m ↝ StateT s (StateT s m) stateI = stateCommute ∘ funit -- # NondetAppendT [Append/Join] -- Commuting with self pluck ∷ [a] → [[a]] → Maybe ([a],[[a]]) pluck [] _ = Nothing pluck (x:xs) [] = Just ([x],[xs]) pluck (x₁:xs₁) (xs₂:xss) = case pluck xs₂ xss of Nothing → Nothing Just (ys₂,xss') → Just (x₁:ys₂,xs₁:xss') transpose ∷ [[a]] → [[a]] transpose [] = [[]] transpose (xs:xss) = case pluck xs xss of Nothing → [] Just (ys,xss') → ys:transpose xss' nondetAppendCommute ∷ (Functor m) ⇒ NondetAppendT (NondetAppendT m) ↝ NondetAppendT (NondetAppendT m) nondetAppendCommute = NondetAppendT ∘ NondetAppendT ∘ map transpose ∘ runNondetAppendT ∘ runNondetAppendT transposeSetLazy ∷ 𝒫ᵇ (𝒫ᵇ a) → 𝒫ᵇ (𝒫ᵇ a) transposeSetLazy = lazySet ∘ map lazySet ∘ transpose ∘ list ∘ map list nondetCommute ∷ (Functor m) ⇒ NondetJoinT (NondetJoinT m) ↝ NondetJoinT (NondetJoinT m) nondetCommute = NondetJoinT ∘ NondetJoinT ∘ map transposeSetLazy ∘ runNondetJoinT ∘ runNondetJoinT -- Monoid, Functor and Monad instance (Functorial Monoid m) ⇒ Monoid (NondetAppendT m a) where null ∷ NondetAppendT m a null = with (functorial ∷ W (Monoid (m [a]))) $ NondetAppendT null (⧺) ∷ NondetAppendT m a → NondetAppendT m a → NondetAppendT m a xs ⧺ ys = with (functorial ∷ W (Monoid (m [a]))) $ NondetAppendT $ runNondetAppendT xs ⧺ runNondetAppendT ys instance (Functorial Monoid m) ⇒ Functorial Monoid (NondetAppendT m) where functorial = W instance (Functorial JoinLattice m) ⇒ Bot (NondetJoinT m a) where bot ∷ NondetJoinT m a bot = with (functorial ∷ W (JoinLattice (m (𝒫ᵇ a)))) $ NondetJoinT bot instance (Functorial JoinLattice m) ⇒ Join (NondetJoinT m a) where (⊔) ∷ NondetJoinT m a → NondetJoinT m a → NondetJoinT m a xs ⊔ ys = with (functorial ∷ W (JoinLattice (m (𝒫ᵇ a)))) $ NondetJoinT $ runNondetJoinT xs ⊔ runNondetJoinT ys instance (Functorial JoinLattice m) ⇒ JoinLattice (NondetJoinT m a) instance (Functorial JoinLattice m) ⇒ Functorial JoinLattice (NondetJoinT m) where functorial = W instance (Functor m) ⇒ Functor (NondetAppendT m) where map ∷ (a → b) → NondetAppendT m a → NondetAppendT m b map f = NondetAppendT ∘ map (map f) ∘ runNondetAppendT instance (Monad m,Functorial Monoid m) ⇒ Monad (NondetAppendT m) where return ∷ a → NondetAppendT m a return = NondetAppendT ∘ return ∘ return (≫=) ∷ NondetAppendT m a → (a → NondetAppendT m b) → NondetAppendT m b aM ≫= k = NondetAppendT $ do xs ← runNondetAppendT aM runNondetAppendT $ concat $ k ^$ xs instance (Functor m) ⇒ Functor (NondetJoinT m) where map ∷ (a → b) → NondetJoinT m a → NondetJoinT m b map f = NondetJoinT ∘ map (map f) ∘ runNondetJoinT instance (Monad m,Functorial JoinLattice m) ⇒ Monad (NondetJoinT m) where return ∷ a → NondetJoinT m a return = NondetJoinT ∘ return ∘ return (≫=) ∷ NondetJoinT m a → (a → NondetJoinT m b) → NondetJoinT m b aM ≫= k = NondetJoinT $ do xs ← runNondetJoinT aM runNondetJoinT $ joins $ k ^$ xs -- Higher Functor instance FunctorUnit NondetAppendT where funit ∷ (Functor m) ⇒ m ↝ NondetAppendT m funit = NondetAppendT ∘ map return instance FunctorDiscard NondetAppendT where fdiscard ∷ (Functor m) ⇒ NondetAppendT (NondetAppendT m) ↝ NondetAppendT m fdiscard = NondetAppendT ∘ concat ^∘ runNondetAppendT ∘ runNondetAppendT instance FunctorFunctor NondetAppendT where fmap ∷ m ↝ n → NondetAppendT m ↝ NondetAppendT n fmap f = NondetAppendT ∘ f ∘ runNondetAppendT instance FunctorUnit NondetJoinT where funit ∷ (Functor m) ⇒ m ↝ NondetJoinT m funit = NondetJoinT ∘ map return instance FunctorDiscard NondetJoinT where fdiscard ∷ (Functor m) ⇒ NondetJoinT (NondetJoinT m) ↝ NondetJoinT m fdiscard = NondetJoinT ∘ joins ^∘ runNondetJoinT ∘ runNondetJoinT instance FunctorFunctor NondetJoinT where fmap ∷ m ↝ n → NondetJoinT m ↝ NondetJoinT n fmap f = NondetJoinT ∘ f ∘ runNondetJoinT -- Monad Monoid instance (Functorial Monoid m) ⇒ MonadMonoid (NondetAppendT m) where {mnull = null;(<⧺>) = (⧺)} instance MonadMonoid [] where {mnull = null;(<⧺>) = (⧺)} instance (Functorial JoinLattice m) ⇒ MonadBot (NondetJoinT m) where mbot = bot instance (Functorial JoinLattice m) ⇒ MonadJoin (NondetJoinT m) where (<⊔>) = (⊔) instance (Functorial JoinLattice m) ⇒ MonadJoinLattice (NondetJoinT m) instance MonadBot 𝒫ᵇ where mbot = bot instance MonadJoin 𝒫ᵇ where (<⊔>) = (⊔) -- Nondet Effect instance (Functor m) ⇒ MonadNondetAppend (NondetAppendT m) where nondetAppendE ∷ NondetAppendT (NondetAppendT m) ↝ NondetAppendT m nondetAppendE = fdiscard ∘ nondetAppendCommute nondetAppendI ∷ NondetAppendT m ↝ NondetAppendT (NondetAppendT m) nondetAppendI = nondetAppendCommute ∘ funit instance (Functor m) ⇒ MonadNondetJoin (NondetJoinT m) where nondetJoinE ∷ NondetJoinT (NondetJoinT m) ↝ NondetJoinT m nondetJoinE = fdiscard ∘ nondetCommute nondetJoinI ∷ NondetJoinT m ↝ NondetJoinT (NondetJoinT m) nondetJoinI = nondetCommute ∘ funit -- # Flow [Append/Join] -- Commuting with self flowCommuteAppend ∷ ∀ s₁ s₂ m. (Functor m,Monoid s₁) ⇒ FlowAppendT s₁ (FlowAppendT s₂ m) ↝ FlowAppendT s₂ (FlowAppendT s₁ m) flowCommuteAppend xMM = FlowAppendT $ \ s₂ → FlowAppendT $ \ s₁ → ff ^$ runFlowAppendT (runFlowAppendT xMM s₁) s₂ where ff ∷ ∀ a. (a ⇰♭⧺ s₁) ⇰♭⧺ s₂ → (a ⇰♭⧺ s₂) ⇰♭⧺ s₁ ff = lazyDictAppend ∘ map (mapFst lazyDictAppend) ∘ map merge ∘ map (mapFst list) ∘ list where merge ∷ ([(a,s₁)],s₂) → ([(a,s₂)],s₁) merge (xs₁s,s₂) = (map (\ (x,_) → (x,s₂)) xs₁s,concat $ map snd xs₁s) flowCommuteJoin ∷ ∀ s₁ s₂ m. (Functor m,JoinLattice s₁) ⇒ FlowJoinT s₁ (FlowJoinT s₂ m) ↝ FlowJoinT s₂ (FlowJoinT s₁ m) flowCommuteJoin xMM = FlowJoinT $ \ s₂ → FlowJoinT $ \ s₁ → ff ^$ runFlowJoinT (runFlowJoinT xMM s₁) s₂ where ff ∷ ∀ a. (a ⇰♭⊔ s₁) ⇰♭⊔ s₂ → (a ⇰♭⊔ s₂) ⇰♭⊔ s₁ ff = lazyDictJoin ∘ map (mapFst lazyDictJoin) ∘ map merge ∘ map (mapFst list) ∘ list where merge ∷ ([(a,s₁)],s₂) → ([(a,s₂)],s₁) merge (xs₁s,s₂) = (map (\ (x,_) → (x,s₂)) xs₁s,joins $ map snd xs₁s) -- Monoid/Functor/Monad instance (Functorial Monoid m,Monoid s) ⇒ Monoid (FlowAppendT s m a) where null ∷ FlowAppendT s m a null = with (functorial ∷ W (Monoid (m (a ⇰♭⧺ s)))) $ FlowAppendT $ \ _ → null (⧺) ∷ FlowAppendT s m a → FlowAppendT s m a → FlowAppendT s m a xss₁ ⧺ xss₂ = with (functorial ∷ W (Monoid (m (a ⇰♭⧺ s)))) $ FlowAppendT $ \ s → runFlowAppendT xss₁ s ⧺ runFlowAppendT xss₂ s instance (Functorial JoinLattice m,JoinLattice s) ⇒ Bot (FlowJoinT s m a) where bot ∷ FlowJoinT s m a bot = with (functorial ∷ W (JoinLattice (m (a ⇰♭⊔ s)))) $ FlowJoinT $ \ _ → bot instance (Functorial JoinLattice m,JoinLattice s) ⇒ Join (FlowJoinT s m a) where (⊔) ∷ FlowJoinT s m a → FlowJoinT s m a → FlowJoinT s m a xss₁ ⊔ xss₂ = with (functorial ∷ W (JoinLattice (m (a ⇰♭⊔ s)))) $ FlowJoinT $ \ s → runFlowJoinT xss₁ s ⊔ runFlowJoinT xss₂ s instance (Functorial JoinLattice m,JoinLattice s) ⇒ JoinLattice (FlowJoinT s m a) instance (Functor m) ⇒ Functor (FlowAppendT s m) where map ∷ (a → b) → FlowAppendT s m a → FlowAppendT s m b map f xM = FlowAppendT $ \ s → map (mapKeyLazyDictAppend f) $ runFlowAppendT xM s instance (Monad m,Functorial Monoid m,Monoid s) ⇒ Monad (FlowAppendT s m) where return ∷ a → FlowAppendT s m a return x = FlowAppendT $ \ s → return $ lazyDictAppend [(x,s)] (≫=) ∷ ∀ a b. FlowAppendT s m a → (a → FlowAppendT s m b) → FlowAppendT s m b xM ≫= f = with (functorial ∷ W (Monoid (m (b ⇰♭⧺ s)))) $ FlowAppendT $ \ s → do xss ← runLazyDictAppend ^$ runFlowAppendT xM s concat $ mapOn xss $ \ (x,s') → runFlowAppendT (f x) s' instance (Functor m) ⇒ Functor (FlowJoinT s m) where map ∷ (a → b) → FlowJoinT s m a → FlowJoinT s m b map f xM = FlowJoinT $ \ s → map (mapKeyLazyDictJoin f) $ runFlowJoinT xM s instance (Monad m,Functorial JoinLattice m,JoinLattice s) ⇒ Monad (FlowJoinT s m) where return ∷ a → FlowJoinT s m a return x = FlowJoinT $ \ s → return $ lazyDictJoin [(x,s)] (≫=) ∷ ∀ a b. FlowJoinT s m a → (a → FlowJoinT s m b) → FlowJoinT s m b xM ≫= f = with (functorial ∷ W (JoinLattice (m (b ⇰♭⊔ s)))) $ FlowJoinT $ \ s → do xss ← runLazyDictJoin ^$ runFlowJoinT xM s joins $ mapOn xss $ \ (x,s') → runFlowJoinT (f x) s' -- Higher Functor instance FunctorUnit (FlowAppendT s) where funit ∷ (Functor m) ⇒ m ↝ FlowAppendT s m funit xM = FlowAppendT $ \ s → ff s ^$ xM where ff s x = lazyDictAppend [(x,s)] instance (Monoid s) ⇒ FunctorDiscard (FlowAppendT s) where fdiscard ∷ ∀ m. (Functor m) ⇒ FlowAppendT s (FlowAppendT s m) ↝ FlowAppendT s m fdiscard xMM = FlowAppendT $ \ s → flip runFlowAppendT s $ ff $ runFlowAppendT xMM s where ff ∷ FlowAppendT s m (a ⇰♭⧺ s) → FlowAppendT s m a ff asM = FlowAppendT $ \ s → lazyDictAppend ∘ concat ∘ map (\ (xs,s') → map (,s') (list xs)) ∘ runLazyDictAppend ^$ runFlowAppendT (map (map fst ∘ runLazyDictAppend) asM) s instance FunctorFunctor (FlowAppendT s) where fmap ∷ m ↝ n → FlowAppendT s m ↝ FlowAppendT s n fmap f xM = FlowAppendT $ \ s → f $ runFlowAppendT xM s instance FunctorUnit (FlowJoinT s) where funit ∷ (Functor m) ⇒ m ↝ FlowJoinT s m funit xM = FlowJoinT $ \ s → ff s ^$ xM where ff s x = lazyDictJoin [(x,s)] instance (JoinLattice s) ⇒ FunctorDiscard (FlowJoinT s) where fdiscard ∷ ∀ m. (Functor m) ⇒ FlowJoinT s (FlowJoinT s m) ↝ FlowJoinT s m fdiscard xMM = FlowJoinT $ \ s → flip runFlowJoinT s $ ff $ runFlowJoinT xMM s where ff ∷ FlowJoinT s m (a ⇰♭⊔ s) → FlowJoinT s m a ff asM = FlowJoinT $ \ s → lazyDictJoin ∘ concat ∘ map (\ (xs,s') → map (,s') (list xs)) ∘ runLazyDictJoin ^$ runFlowJoinT (map (map fst ∘ runLazyDictJoin) asM) s instance FunctorFunctor (FlowJoinT s) where fmap ∷ m ↝ n → FlowJoinT s m ↝ FlowJoinT s n fmap f xM = FlowJoinT $ \ s → f $ runFlowJoinT xM s -- Sum Effects instance (Monoid s,Functorial Monoid m) ⇒ MonadMonoid (FlowAppendT s m) where {mnull = null;(<⧺>) = (⧺)} instance (JoinLattice s,Functorial JoinLattice m) ⇒ MonadBot (FlowJoinT s m) where mbot = bot instance (JoinLattice s,Functorial JoinLattice m) ⇒ MonadJoin (FlowJoinT s m) where (<⊔>) = (⊔) instance (JoinLattice s,Functorial JoinLattice m) ⇒ MonadJoinLattice (FlowJoinT s m) -- Flow Effect instance (Functor m,Monoid s) ⇒ MonadFlowAppend s (FlowAppendT s m) where flowAppendE ∷ FlowAppendT s (FlowAppendT s m) ↝ FlowAppendT s m flowAppendE = fdiscard ∘ flowCommuteAppend flowAppendI ∷ FlowAppendT s m ↝ FlowAppendT s (FlowAppendT s m) flowAppendI = flowCommuteAppend ∘ funit instance (Functor m,JoinLattice s) ⇒ MonadFlowJoin s (FlowJoinT s m) where flowJoinE ∷ FlowJoinT s (FlowJoinT s m) ↝ FlowJoinT s m flowJoinE = fdiscard ∘ flowCommuteJoin flowJoinI ∷ FlowJoinT s m ↝ FlowJoinT s (FlowJoinT s m) flowJoinI = flowCommuteJoin ∘ funit -- Also supports state effects flowJoinFromState ∷ (Functor m) ⇒ StateT s m ↝ FlowJoinT s m flowJoinFromState xM = FlowJoinT $ \ s → ff ^$ runStateT xM s where ff ∷ (a,s) → a ⇰♭⊔ s ff = lazyDictJoin ∘ singleFold flowJoinStateI ∷ (Functor m) ⇒ FlowJoinT s m ↝ StateT s (FlowJoinT s m) flowJoinStateI xsM = StateT $ \ s → FlowJoinT $ \ s₀ → ff s₀ ^$ runFlowJoinT xsM s where ff ∷ s → a ⇰♭⊔ s → (a,s) ⇰♭⊔ s ff s₀ = lazyDictJoin ∘ map (,s₀) ∘ list instance (Functor m,JoinLattice s) ⇒ MonadState s (FlowJoinT s m) where stateE ∷ StateT s (FlowJoinT s m) ↝ FlowJoinT s m stateE = flowJoinE ∘ flowJoinFromState stateI ∷ FlowJoinT s m ↝ StateT s (FlowJoinT s m) stateI = flowJoinStateI -- # ContT -- Base Effect type Cont r = ContT r ID cont ∷ ((a → r) → r) → Cont r a cont k = ContT $ \ k' → ID $ k $ \ a → runID $ k' a runCont ∷ Cont r a → (a → r) → r runCont aM f = runID $ runContT aM (ID ∘ f) evalCont ∷ Cont r r → r evalCont aM = runCont aM id -- Functor and Monad instance Functor (ContT r m) where map = mmap instance Monad (ContT r m) where return ∷ a → ContT r m a return a = ContT $ \ k → k a (≫=) ∷ ContT r m a → (a → ContT r m b) → ContT r m b aM ≫= kM = ContT $ \ (k ∷ b → m r) → runContT aM $ \ a → runContT (kM a) k -- Higher Functor instance FunctorIsoFunctor (ContT r) where fisomap ∷ (m ↝ n,n ↝ m) → (ContT r m ↝ ContT r n) fisomap (to,from) aM = ContT $ \ (k ∷ a → n r) → to $ runContT aM $ \ a → from $ k a -- Cont Effect instance (Monad m) ⇒ MonadCont r (ContT r m) where contE ∷ ContT r (ContT r m) ↝ ContT r m contE aMM = ContT $ \ (k ∷ a → m r) → evalContT $ runContT aMM $ \ a → ContT $ \ (k' ∷ r → m r) → k' *$ k a contI ∷ ContT r m ↝ ContT r (ContT r m) contI aM = ContT $ \ (k₁ ∷ a → ContT r m r) → ContT $ \ (k₂ ∷ r → m r) → k₂ *$ runContT aM $ \ a → evalContT (k₁ a) -- # OpaqueContT -- Base Effect type OpaqueCont k r = OpaqueContT k r ID opaqueCont ∷ (k r ID a → r) → OpaqueCont k r a opaqueCont nk = OpaqueContT $ ID ∘ nk runOpaqueCont ∷ OpaqueCont k r a → k r ID a → r runOpaqueCont = runID ∘∘ runOpaqueContT metaCont ∷ (Isomorphic3 (k r) (ContFun r)) ⇒ ((a → r) → r) → OpaqueCont k r a metaCont nk = opaqueCont $ \ (k ∷ k r ID a) → nk $ (∘) runID ∘ runContFun $ isoTo3 isomorphic3 k runMetaCont ∷ (Isomorphic3 (ContFun r) (k r)) ⇒ OpaqueCont k r a → (a → r) → r runMetaCont aM k = runOpaqueCont aM $ isoTo3 isomorphic3 $ ContFun $ ID ∘ k evalOpaqueCont ∷ (Isomorphic3 (ContFun r) (k r)) ⇒ OpaqueCont k r r → r evalOpaqueCont aM = runMetaCont aM id -- Functor and Monad instance (Monad m,Isomorphic3 (ContFun r) (k r)) ⇒ Functor (OpaqueContT k r m) where map = mmap instance (Monad m,Isomorphic3 (ContFun r) (k r)) ⇒ Monad (OpaqueContT k r m) where return ∷ a → OpaqueContT k r m a return a = OpaqueContT $ \ k → runContFun (isoFrom3 isomorphic3 k) a (≫=) ∷ OpaqueContT k r m a → (a → OpaqueContT k r m b) → OpaqueContT k r m b aM ≫= kM = OpaqueContT $ \ (k ∷ k r m a) → runMetaContT aM $ \ a → runOpaqueContT (kM a) k -- Higher Functor instance (Isomorphic3 (ContFun r) (k r)) ⇒ FunctorIsoFunctor (OpaqueContT k r) where fisomap ∷ (m ↝ n,n ↝ m) → OpaqueContT k r m ↝ OpaqueContT k r n fisomap tofrom = opaque ∘ fisomap tofrom ∘ meta -- OpaqueCont Effect class Balloon k r | k → r where inflate ∷ (Monad m) ⇒ k r m ↝ k r (OpaqueContT k r m) deflate ∷ (Monad m) ⇒ k r (OpaqueContT k r m) ↝ k r m instance (Monad m,Isomorphic3 (ContFun r) (k r),Balloon k r) ⇒ MonadOpaqueCont k r (OpaqueContT k r m) where opaqueContE ∷ OpaqueContT k r (OpaqueContT k r m) a → OpaqueContT k r m a opaqueContE kk = OpaqueContT $ \ (k ∷ k r m a ) → runMetaContTWith return $ runOpaqueContT kk $ inflate k opaqueContI ∷ OpaqueContT k r m a → OpaqueContT k r (OpaqueContT k r m) a opaqueContI aM = OpaqueContT $ \ k₁ → metaContT $ \ (k₂ ∷ r → m r) → k₂ *$ runOpaqueContT aM $ deflate k₁ instance (Monad m,Isomorphic3 (ContFun r) (k r)) ⇒ MonadCont r (OpaqueContT k r m) where contE ∷ ContT r (OpaqueContT k r m) ↝ OpaqueContT k r m contE aMM = metaContT $ \ (k ∷ a → m r) → runMetaContTWith return $ runContT aMM $ \ a → metaContT $ \ (k' ∷ r → m r) → k' *$ k a contI ∷ OpaqueContT k r m ↝ ContT r (OpaqueContT k r m) contI aM = ContT $ \ (k₁ ∷ a → OpaqueContT k r m r) → metaContT $ \ (k₂ ∷ r → m r) → k₂ *$ runMetaContT aM $ \ a → runMetaContT (k₁ a) return ---------------------- -- Monads Commuting -- ---------------------- -- # Failure // * -- ## Failure // Error [ISO] failureErrorCommute ∷ (Functor m) ⇒ FailureT (ErrorT e m) ↝ ErrorT e (FailureT m) failureErrorCommute = ErrorT ∘ FailureT ∘ map ff ∘ runErrorT ∘ runFailureT where ff ∷ (e ⨄ Maybe a) → Maybe (e ⨄ a) ff (Left e) = Just (Left e) ff (Right Nothing) = Nothing ff (Right (Just x)) = Just (Right x) errorFailureCommute ∷ (Functor m) ⇒ ErrorT e (FailureT m) ↝ FailureT (ErrorT e m) errorFailureCommute = FailureT ∘ ErrorT ∘ map ff ∘ runFailureT ∘ runErrorT where ff ∷ Maybe (e ⨄ a) → (e ⨄ Maybe a) ff Nothing = Right Nothing ff (Just (Left e)) = Left e ff (Just (Right x)) = Right (Just x) instance (Functor m,MonadFailure m) ⇒ MonadFailure (ErrorT e m) where failureE ∷ FailureT (ErrorT e m) ↝ ErrorT e m failureE = fmap failureE ∘ failureErrorCommute failureI ∷ ErrorT e m ↝ FailureT (ErrorT e m) failureI = errorFailureCommute ∘ fmap failureI instance (Functor m,MonadError e m) ⇒ MonadError e (FailureT m) where errorE ∷ ErrorT e (FailureT m) ↝ FailureT m errorE = fmap errorE ∘ errorFailureCommute errorI ∷ FailureT m ↝ ErrorT e (FailureT m) errorI = failureErrorCommute ∘ fmap errorI -- ## Failure // Reader [ISO] failureReaderCommute ∷ (Functor m) ⇒ FailureT (ReaderT r m) ↝ ReaderT r (FailureT m) failureReaderCommute aMRM = ReaderT $ \ r → FailureT $ runReaderTWith r $ runFailureT aMRM readerFailureCommute ∷ (Functor m) ⇒ ReaderT r (FailureT m) ↝ FailureT (ReaderT r m) readerFailureCommute aRMM = FailureT $ ReaderT $ \ r → runFailureT $ runReaderTWith r aRMM instance (Functor m,MonadFailure m) ⇒ MonadFailure (ReaderT r m) where failureE ∷ FailureT (ReaderT r m) ↝ ReaderT r m failureE = fmap failureE ∘ failureReaderCommute failureI ∷ ReaderT r m ↝ FailureT (ReaderT r m) failureI = readerFailureCommute ∘ fmap failureI instance (Functor m,MonadReader r m) ⇒ MonadReader r (FailureT m) where readerE ∷ ReaderT r (FailureT m) ↝ FailureT m readerE = fmap readerE ∘ readerFailureCommute readerI ∷ FailureT m ↝ ReaderT r (FailureT m) readerI = failureReaderCommute ∘ fmap readerI -- ## Failure // Writer [ADJ] failureWriterCommute ∷ (Functor m) ⇒ FailureT (WriterT o m) ↝ WriterT o (FailureT m) failureWriterCommute aMRM = WriterT $ FailureT $ ff ^$ runWriterT $ runFailureT aMRM where ff ∷ (Maybe a,o) → Maybe (a,o) ff (Nothing,_) = Nothing ff (Just a,o) = Just (a,o) writerFailureCommute ∷ (Monoid o,Functor m) ⇒ WriterT o (FailureT m) ↝ FailureT (WriterT o m) writerFailureCommute aRMM = FailureT $ WriterT $ ff ^$ runFailureT $ runWriterT aRMM where ff ∷ (Monoid o) ⇒ Maybe (a,o) → (Maybe a,o) ff Nothing = (Nothing,null) ff (Just (a,o)) = (Just a,o) instance (Functor m,MonadFailure m,Monoid o) ⇒ MonadFailure (WriterT o m) where failureE ∷ FailureT (WriterT o m) ↝ WriterT o m failureE = fmap failureE ∘ failureWriterCommute failureI ∷ WriterT o m ↝ FailureT (WriterT o m) failureI = writerFailureCommute ∘ fmap failureI instance (Functor m,MonadWriter o m,Monoid o) ⇒ MonadWriter o (FailureT m) where writerE ∷ WriterT o (FailureT m) ↝ FailureT m writerE = fmap writerE ∘ writerFailureCommute writerI ∷ FailureT m ↝ WriterT o (FailureT m) writerI = failureWriterCommute ∘ fmap writerI -- ## Failure // State [ADJ] failureStateCommute ∷ ∀ s m. (Functor m) ⇒ FailureT (StateT s m) ↝ StateT s (FailureT m) failureStateCommute aMSM = StateT $ \ s₁ → FailureT $ ff ^$ runStateTWith s₁ $ runFailureT aMSM where ff ∷ (Maybe a,s) → Maybe (a,s) ff (Nothing,_) = Nothing ff (Just a,s₂) = Just (a,s₂) stateFailureCommute ∷ ∀ s m. (Functor m) ⇒ StateT s (FailureT m) ↝ FailureT (StateT s m) stateFailureCommute aSMM = FailureT $ StateT $ \ s₁ → ff s₁ ^$ runFailureT $ runStateTWith s₁ aSMM where ff ∷ s → (Maybe (a,s)) → (Maybe a,s) ff s₁ Nothing = (Nothing,s₁) ff _ (Just (a,s₂)) = (Just a,s₂) instance (Functor m,MonadFailure m) ⇒ MonadFailure (StateT s m) where failureE ∷ FailureT (StateT s m) ↝ StateT s m failureE = fmap failureE ∘ failureStateCommute failureI ∷ StateT s m ↝ FailureT (StateT s m) failureI = stateFailureCommute ∘ fmap failureI instance (Functor m,MonadState s m) ⇒ MonadState s (FailureT m) where stateE ∷ StateT s (FailureT m) ↝ FailureT m stateE = fmap stateE ∘ stateFailureCommute stateI ∷ FailureT m ↝ StateT s (FailureT m) stateI = failureStateCommute ∘ fmap stateI -- ## Failure // Nondet [ADJ] failureNondetAppendCommute ∷ (Functor m) ⇒ FailureT (NondetAppendT m) ↝ NondetAppendT (FailureT m) failureNondetAppendCommute = NondetAppendT ∘ FailureT ∘ map ff ∘ runNondetAppendT ∘ runFailureT where ff ∷ [Maybe a] → Maybe [a] ff [] = Just [] ff (Nothing:_) = Nothing ff (Just x:xMs) = (x:) ^$ ff xMs nondetAppendFailureCommute ∷ (Functor m) ⇒ NondetAppendT (FailureT m) ↝ FailureT (NondetAppendT m) nondetAppendFailureCommute = FailureT ∘ NondetAppendT ∘ map ff ∘ runFailureT ∘ runNondetAppendT where ff ∷ Maybe [a] → [Maybe a] ff Nothing = [Nothing] ff (Just xs) = map Just xs instance (Functor m,MonadFailure m) ⇒ MonadFailure (NondetAppendT m) where failureE ∷ FailureT (NondetAppendT m) ↝ NondetAppendT m failureE = fmap failureE ∘ failureNondetAppendCommute failureI ∷ NondetAppendT m ↝ FailureT (NondetAppendT m) failureI = nondetAppendFailureCommute ∘ fmap failureI instance (Functor m,MonadNondetAppend m) ⇒ MonadNondetAppend (FailureT m) where nondetAppendE ∷ NondetAppendT (FailureT m) ↝ FailureT m nondetAppendE = fmap nondetAppendE ∘ nondetAppendFailureCommute nondetAppendI ∷ FailureT m ↝ NondetAppendT (FailureT m) nondetAppendI = failureNondetAppendCommute ∘ fmap nondetAppendI failureNondetCommute ∷ (Functor m) ⇒ FailureT (NondetJoinT m) ↝ NondetJoinT (FailureT m) failureNondetCommute = NondetJoinT ∘ FailureT ∘ map (map lazySet ∘ ff ∘ list) ∘ runNondetJoinT ∘ runFailureT where ff ∷ [Maybe a] → Maybe [a] ff [] = Just [] ff (Nothing:_) = Nothing ff (Just x:xMs) = (x:) ^$ ff xMs nondetFailureCommute ∷ (Functor m) ⇒ NondetJoinT (FailureT m) ↝ FailureT (NondetJoinT m) nondetFailureCommute = FailureT ∘ NondetJoinT ∘ map (lazySet ∘ ff ∘ map list) ∘ runFailureT ∘ runNondetJoinT where ff ∷ Maybe [a] → [Maybe a] ff Nothing = [Nothing] ff (Just xs) = map Just xs instance (Functor m,MonadFailure m) ⇒ MonadFailure (NondetJoinT m) where failureE ∷ FailureT (NondetJoinT m) ↝ NondetJoinT m failureE = fmap failureE ∘ failureNondetCommute failureI ∷ NondetJoinT m ↝ FailureT (NondetJoinT m) failureI = nondetFailureCommute ∘ fmap failureI instance (Functor m,MonadNondetJoin m) ⇒ MonadNondetJoin (FailureT m) where nondetJoinE ∷ NondetJoinT (FailureT m) ↝ FailureT m nondetJoinE = fmap nondetJoinE ∘ nondetFailureCommute nondetJoinI ∷ FailureT m ↝ NondetJoinT (FailureT m) nondetJoinI = failureNondetCommute ∘ fmap nondetJoinI -- TODO: FlowAppendT -- ## Failure // Cont -- TODO: -- ## Failure // OpaqueCont -- TODO: -- # Error // * -- ## Error // Reader [ISO] errorReaderCommute ∷ ErrorT e (ReaderT r m) ↝ ReaderT r (ErrorT e m) errorReaderCommute aMRM = ReaderT $ \ r → ErrorT $ runReaderTWith r $ runErrorT aMRM readerErrorCommute ∷ ReaderT r (ErrorT e m) ↝ ErrorT e (ReaderT r m) readerErrorCommute aRMM = ErrorT $ ReaderT $ \ r → runErrorT $ runReaderTWith r aRMM instance (Functor m,MonadError e m) ⇒ MonadError e (ReaderT r m) where errorE ∷ ErrorT e (ReaderT r m) ↝ ReaderT r m errorE = fmap errorE ∘ errorReaderCommute errorI ∷ ReaderT r m ↝ ErrorT e (ReaderT r m) errorI = readerErrorCommute ∘ fmap errorI instance (Functor m,MonadReader r m) ⇒ MonadReader r (ErrorT e m) where readerE ∷ ReaderT r (ErrorT e m) ↝ ErrorT e m readerE = fmap readerE ∘ readerErrorCommute readerI ∷ ErrorT e m ↝ ReaderT r (ErrorT e m) readerI = errorReaderCommute ∘ fmap readerI -- ## Error // Writer [ADJ] errorWriterCommute ∷ ∀ e o m. (Functor m) ⇒ ErrorT e (WriterT o m) ↝ WriterT o (ErrorT e m) errorWriterCommute = WriterT ∘ ErrorT ∘ ff ^∘ runWriterT ∘ runErrorT where ff ∷ (e ⨄ a,o) → (e ⨄ (a,o)) ff (Left e,_) = Left e ff (Right a,o) = Right (a,o) writerErrorCommute ∷ (Functor m,Monoid o) ⇒ WriterT o (ErrorT e m) ↝ ErrorT e (WriterT o m) writerErrorCommute = ErrorT ∘ WriterT ∘ ff ^∘ runErrorT ∘ runWriterT where ff ∷ (Monoid o) ⇒ (e ⨄ (a,o)) → (e ⨄ a,o) ff (Left e) = (Left e,null) ff (Right (a,o)) = (Right a,o) instance (Functor m,MonadError e m,Monoid o) ⇒ MonadError e (WriterT o m) where errorE ∷ ErrorT e (WriterT o m) ↝ WriterT o m errorE = fmap errorE ∘ errorWriterCommute errorI ∷ WriterT o m ↝ ErrorT e (WriterT o m) errorI = writerErrorCommute ∘ fmap errorI instance (Functor m,MonadWriter o m,Monoid o) ⇒ MonadWriter o (ErrorT e m) where writerE ∷ WriterT o (ErrorT e m) ↝ ErrorT e m writerE = fmap writerE ∘ writerErrorCommute writerI ∷ ErrorT e m ↝ WriterT o (ErrorT e m) writerI = errorWriterCommute ∘ fmap writerI -- ## Error // State [ADJ] errorStateCommute ∷ (Functor m) ⇒ ErrorT e (StateT s m) ↝ StateT s (ErrorT e m) errorStateCommute aMRM = StateT $ \ s → ErrorT $ ff ^$ runStateTWith s $ runErrorT aMRM where ff ∷ (e ⨄ a,s) → e ⨄ (a,s) ff (Left e,_) = Left e ff (Right a,s) = Right (a,s) stateErrorCommute ∷ (Functor m) ⇒ StateT s (ErrorT e m) ↝ ErrorT e (StateT s m) stateErrorCommute aRMM = ErrorT $ StateT $ \ s → ff s ^$ runErrorT $ runStateTWith s aRMM where ff ∷ s → e ⨄ (a,s) → (e ⨄ a,s) ff s (Left e) = (Left e,s) ff _ (Right (a,s)) = (Right a,s) instance (Functor m,MonadError e m) ⇒ MonadError e (StateT s m) where errorE ∷ ErrorT e (StateT s m) ↝ StateT s m errorE = fmap errorE ∘ errorStateCommute errorI ∷ StateT s m ↝ ErrorT e (StateT s m) errorI = stateErrorCommute ∘ fmap errorI instance (Functor m,MonadState s m) ⇒ MonadState s (ErrorT e m) where stateE ∷ StateT s (ErrorT e m) ↝ ErrorT e m stateE = fmap stateE ∘ stateErrorCommute stateI ∷ ErrorT e m ↝ StateT s (ErrorT e m) stateI = errorStateCommute ∘ fmap stateI -- ## Error // Nondet [ADJ] errorNondetAppendCommute ∷ (Functor m) ⇒ ErrorT e (NondetAppendT m) ↝ NondetAppendT (ErrorT e m) errorNondetAppendCommute = NondetAppendT ∘ ErrorT ∘ map ff ∘ runNondetAppendT ∘ runErrorT where ff ∷ [e ⨄ a] → e ⨄ [a] ff [] = Right [] ff (Left e:_) = Left e ff (Right x:xsM) = (x:) ^$ ff xsM nondetAppendErrorCommute ∷ (Functor m) ⇒ NondetAppendT (ErrorT e m) ↝ ErrorT e (NondetAppendT m) nondetAppendErrorCommute = ErrorT ∘ NondetAppendT ∘ map ff ∘ runErrorT ∘ runNondetAppendT where ff ∷ e ⨄ [a] → [e ⨄ a] ff (Left e) = [Left e] ff (Right xs) = map Right xs instance (Functor m,MonadError e m) ⇒ MonadError e (NondetAppendT m) where errorE ∷ ErrorT e (NondetAppendT m) ↝ NondetAppendT m errorE = fmap errorE ∘ errorNondetAppendCommute errorI ∷ NondetAppendT m ↝ ErrorT e (NondetAppendT m) errorI = nondetAppendErrorCommute ∘ fmap errorI instance (Functor m,MonadNondetAppend m) ⇒ MonadNondetAppend (ErrorT e m) where nondetAppendE ∷ NondetAppendT (ErrorT e m) ↝ ErrorT e m nondetAppendE = fmap nondetAppendE ∘ nondetAppendErrorCommute nondetAppendI ∷ ErrorT e m ↝ NondetAppendT (ErrorT e m) nondetAppendI = errorNondetAppendCommute ∘ fmap nondetAppendI errorNondetCommute ∷ (Functor m) ⇒ ErrorT e (NondetJoinT m) ↝ NondetJoinT (ErrorT e m) errorNondetCommute = NondetJoinT ∘ ErrorT ∘ map (map lazySet ∘ ff ∘ list) ∘ runNondetJoinT ∘ runErrorT where ff ∷ [e ⨄ a] → e ⨄ [a] ff [] = Right [] ff (Left e:_) = Left e ff (Right x:xsM) = (x:) ^$ ff xsM nondetErrorCommute ∷ (Functor m) ⇒ NondetJoinT (ErrorT e m) ↝ ErrorT e (NondetJoinT m) nondetErrorCommute = ErrorT ∘ NondetJoinT ∘ map (lazySet ∘ ff ∘ map list) ∘ runErrorT ∘ runNondetJoinT where ff ∷ e ⨄ [a] → [e ⨄ a] ff (Left e) = [Left e] ff (Right xs) = map Right xs instance (Functor m,MonadError e m) ⇒ MonadError e (NondetJoinT m) where errorE ∷ ErrorT e (NondetJoinT m) ↝ NondetJoinT m errorE = fmap errorE ∘ errorNondetCommute errorI ∷ NondetJoinT m ↝ ErrorT e (NondetJoinT m) errorI = nondetErrorCommute ∘ fmap errorI instance (Functor m,MonadNondetJoin m) ⇒ MonadNondetJoin (ErrorT e m) where nondetJoinE ∷ NondetJoinT (ErrorT e m) ↝ ErrorT e m nondetJoinE = fmap nondetJoinE ∘ nondetErrorCommute nondetJoinI ∷ ErrorT e m ↝ NondetJoinT (ErrorT e m) nondetJoinI = errorNondetCommute ∘ fmap nondetJoinI -- TODO: FlowAppendT -- ## Error // Cont -- TODO: -- ## Error // OpaqueCont -- TODO: -- # Reader // * -- ## Reader // Writer [ISO] readerWriterCommute ∷ ReaderT r (WriterT o m) ↝ WriterT o (ReaderT r m) readerWriterCommute aRWM = WriterT $ ReaderT $ \ r → runWriterT $ runReaderTWith r aRWM writerReaderCommute ∷ WriterT o (ReaderT r m) ↝ ReaderT r (WriterT o m) writerReaderCommute aWRM = ReaderT $ \ r → WriterT $ runReaderTWith r $ runWriterT aWRM instance (Functor m,MonadReader r m) ⇒ MonadReader r (WriterT o m) where readerE ∷ ReaderT r (WriterT o m) ↝ WriterT o m readerE = fmap readerE ∘ readerWriterCommute readerI ∷ WriterT o m ↝ ReaderT r (WriterT o m) readerI = writerReaderCommute ∘ fmap readerI instance (Functor m,MonadWriter o m) ⇒ MonadWriter o (ReaderT r m) where writerE ∷ WriterT o (ReaderT r m) ↝ ReaderT r m writerE = fmap writerE ∘ writerReaderCommute writerI ∷ ReaderT r m ↝ WriterT o (ReaderT r m) writerI = readerWriterCommute ∘ fmap writerI -- ## Reader // State [ISO] readerStateCommute ∷ (Functor m) ⇒ ReaderT r (StateT s m) ↝ StateT s (ReaderT r m) readerStateCommute aRSM = StateT $ \ s → ReaderT $ \ r → runStateTWith s $ runReaderTWith r aRSM stateReaderCommute ∷ (Functor m) ⇒ StateT s (ReaderT r m) ↝ ReaderT r (StateT s m) stateReaderCommute aSRM = ReaderT $ \ r → StateT $ \ s → runReaderTWith r $ runStateTWith s aSRM instance (Functor m,MonadReader r m) ⇒ MonadReader r (StateT s m) where readerE ∷ ReaderT r (StateT s m) ↝ StateT s m readerE = fmap readerE ∘ readerStateCommute readerI ∷ StateT s m ↝ ReaderT r (StateT s m) readerI = stateReaderCommute ∘ fmap readerI instance (Functor m,MonadState s m) ⇒ MonadState s (ReaderT r m) where stateE ∷ StateT s (ReaderT r m) ↝ ReaderT r m stateE = fmap stateE ∘ stateReaderCommute stateI ∷ ReaderT r m ↝ StateT s (ReaderT r m) stateI = readerStateCommute ∘ fmap stateI -- ## Reader // Nondet [ISO] readerNondetAppendCommute ∷ (Functor m) ⇒ ReaderT r (NondetAppendT m) ↝ NondetAppendT (ReaderT r m) readerNondetAppendCommute aM = NondetAppendT $ ReaderT $ \ r → runNondetAppendT $ runReaderTWith r aM nondetAppendReaderCommute ∷ (Functor m) ⇒ NondetAppendT (ReaderT r m) ↝ ReaderT r (NondetAppendT m) nondetAppendReaderCommute aM = ReaderT $ \ r → NondetAppendT $ runReaderTWith r $ runNondetAppendT aM instance (Functor m,MonadReader r m) ⇒ MonadReader r (NondetAppendT m) where readerE ∷ ReaderT r (NondetAppendT m) ↝ NondetAppendT m readerE = fmap readerE ∘ readerNondetAppendCommute readerI ∷ NondetAppendT m ↝ ReaderT r (NondetAppendT m) readerI = nondetAppendReaderCommute ∘ fmap readerI instance (Functor m,MonadNondetAppend m) ⇒ MonadNondetAppend (ReaderT r m) where nondetAppendE ∷ NondetAppendT (ReaderT r m) ↝ ReaderT r m nondetAppendE = fmap nondetAppendE ∘ nondetAppendReaderCommute nondetAppendI ∷ ReaderT r m ↝ NondetAppendT (ReaderT r m) nondetAppendI = readerNondetAppendCommute ∘ fmap nondetAppendI readerNondetCommute ∷ (Functor m) ⇒ ReaderT r (NondetJoinT m) ↝ NondetJoinT (ReaderT r m) readerNondetCommute aM = NondetJoinT $ ReaderT $ \ r → runNondetJoinT $ runReaderTWith r aM nondetReaderCommute ∷ (Functor m) ⇒ NondetJoinT (ReaderT r m) ↝ ReaderT r (NondetJoinT m) nondetReaderCommute aM = ReaderT $ \ r → NondetJoinT $ runReaderTWith r $ runNondetJoinT aM instance (Functor m,MonadReader r m) ⇒ MonadReader r (NondetJoinT m) where readerE ∷ ReaderT r (NondetJoinT m) ↝ NondetJoinT m readerE = fmap readerE ∘ readerNondetCommute readerI ∷ NondetJoinT m ↝ ReaderT r (NondetJoinT m) readerI = nondetReaderCommute ∘ fmap readerI instance (Functor m,MonadNondetJoin m) ⇒ MonadNondetJoin (ReaderT r m) where nondetJoinE ∷ NondetJoinT (ReaderT r m) ↝ ReaderT r m nondetJoinE = fmap nondetJoinE ∘ nondetReaderCommute nondetJoinI ∷ ReaderT r m ↝ NondetJoinT (ReaderT r m) nondetJoinI = readerNondetCommute ∘ fmap nondetJoinI -- ## Reader // Flow [???] readerFlowAppendCommute ∷ ∀ r s m. (Functor m) ⇒ ReaderT r (FlowAppendT s m) ↝ FlowAppendT s (ReaderT r m) readerFlowAppendCommute xMM = FlowAppendT $ \ s → ReaderT $ \ r → runFlowAppendT (runReaderT xMM r) s flowAppendReaderCommute ∷ ∀ s r m. (Functor m) ⇒ FlowAppendT s (ReaderT r m) ↝ ReaderT r (FlowAppendT s m) flowAppendReaderCommute xMM = ReaderT $ \ r → FlowAppendT $ \ s → runReaderT (runFlowAppendT xMM s) r instance (Functor m,MonadReader r m) ⇒ MonadReader r (FlowAppendT s m) where readerE ∷ ReaderT r (FlowAppendT s m) ↝ FlowAppendT s m readerE = fmap readerE ∘ readerFlowAppendCommute readerI ∷ FlowAppendT s m ↝ ReaderT r (FlowAppendT s m) readerI = flowAppendReaderCommute ∘ fmap readerI instance (Functor m,MonadFlowAppend s m) ⇒ MonadFlowAppend s (ReaderT r m) where flowAppendE ∷ FlowAppendT s (ReaderT r m) ↝ ReaderT r m flowAppendE = fmap flowAppendE ∘ flowAppendReaderCommute flowAppendI ∷ ReaderT r m ↝ FlowAppendT s (ReaderT r m) flowAppendI = readerFlowAppendCommute ∘ fmap flowAppendI readerFlowJoinCommute ∷ ∀ r s m. (Functor m) ⇒ ReaderT r (FlowJoinT s m) ↝ FlowJoinT s (ReaderT r m) readerFlowJoinCommute xMM = FlowJoinT $ \ s → ReaderT $ \ r → runFlowJoinT (runReaderT xMM r) s flowJoinReaderCommute ∷ ∀ s r m. (Functor m) ⇒ FlowJoinT s (ReaderT r m) ↝ ReaderT r (FlowJoinT s m) flowJoinReaderCommute xMM = ReaderT $ \ r → FlowJoinT $ \ s → runReaderT (runFlowJoinT xMM s) r instance (Functor m,MonadReader r m) ⇒ MonadReader r (FlowJoinT s m) where readerE ∷ ReaderT r (FlowJoinT s m) ↝ FlowJoinT s m readerE = fmap readerE ∘ readerFlowJoinCommute readerI ∷ FlowJoinT s m ↝ ReaderT r (FlowJoinT s m) readerI = flowJoinReaderCommute ∘ fmap readerI instance (Functor m,MonadFlowJoin s m) ⇒ MonadFlowJoin s (ReaderT r m) where flowJoinE ∷ FlowJoinT s (ReaderT r m) ↝ ReaderT r m flowJoinE = fmap flowJoinE ∘ flowJoinReaderCommute flowJoinI ∷ ReaderT r m ↝ FlowJoinT s (ReaderT r m) flowJoinI = readerFlowJoinCommute ∘ fmap flowJoinI -- ## Reader // Cont -- TODO -- ## Reader // OpaqueCont -- TODO -- # Writer // * -- ## Writer // State [ISO] writerStateCommute ∷ ∀ o s m. (Functor m) ⇒ WriterT o (StateT s m) ↝ StateT s (WriterT o m) writerStateCommute aRMM = StateT $ \ s₁ → WriterT $ ff ^$ runStateTWith s₁ $ runWriterT aRMM where ff ∷ ((a,o),s) → ((a,s),o) ff ((a,o),s) = ((a,s),o) stateWriterCommute ∷ ∀ o s m. (Functor m) ⇒ StateT s (WriterT o m) ↝ WriterT o (StateT s m) stateWriterCommute aMRM = WriterT $ StateT $ ff ^∘ runWriterT ∘ runStateT aMRM where ff ∷ ((a,s),o) → ((a,o),s) ff ((a,s),o) = ((a,o),s) instance (Functor m,MonadWriter o m) ⇒ MonadWriter o (StateT s m) where writerE ∷ WriterT o (StateT s m) ↝ StateT s m writerE = fmap writerE ∘ writerStateCommute writerI ∷ StateT s m ↝ WriterT o (StateT s m) writerI = stateWriterCommute ∘ fmap writerI instance (Functor m,MonadState s m) ⇒ MonadState s (WriterT o m) where stateE ∷ StateT s (WriterT o m) ↝ WriterT o m stateE = fmap stateE ∘ stateWriterCommute stateI ∷ WriterT o m ↝ StateT s (WriterT o m) stateI = writerStateCommute ∘ fmap stateI -- ## Writer // Nondet [ADJ] writerNondetAppendCommute ∷ ∀ o m. (Functor m,Monoid o) ⇒ WriterT o (NondetAppendT m) ↝ NondetAppendT (WriterT o m) writerNondetAppendCommute = NondetAppendT ∘ WriterT ∘ ff ^∘ runNondetAppendT ∘ runWriterT where ff ∷ [(a,o)] → ([a],o) ff asL = (fst ^$ asL,concat $ snd ^$ asL) nondetAppendWriterCommute ∷ ∀ o m. (Functor m) ⇒ NondetAppendT (WriterT o m) ↝ WriterT o (NondetAppendT m) nondetAppendWriterCommute = WriterT ∘ NondetAppendT ∘ ff ^∘ runWriterT ∘ runNondetAppendT where ff ∷ ([a],o) → [(a,o)] ff (xs,o) = (,o) ^$ xs instance (Functor m,MonadWriter o m,Monoid o) ⇒ MonadWriter o (NondetAppendT m) where writerE ∷ WriterT o (NondetAppendT m) ↝ NondetAppendT m writerE = fmap writerE ∘ writerNondetAppendCommute writerI ∷ NondetAppendT m ↝ WriterT o (NondetAppendT m) writerI = nondetAppendWriterCommute ∘ fmap writerI instance (Functor m,MonadNondetAppend m,Monoid o) ⇒ MonadNondetAppend (WriterT o m) where nondetAppendE ∷ NondetAppendT (WriterT o m) ↝ WriterT o m nondetAppendE = fmap nondetAppendE ∘ nondetAppendWriterCommute nondetAppendI ∷ WriterT o m ↝ NondetAppendT (WriterT o m) nondetAppendI = writerNondetAppendCommute ∘ fmap nondetAppendI writerNondetJoinCommute ∷ ∀ o m. (Functor m,Monoid o) ⇒ WriterT o (NondetJoinT m) ↝ NondetJoinT (WriterT o m) writerNondetJoinCommute = NondetJoinT ∘ WriterT ∘ (mapFst lazySet ∘ ff ∘ list) ^∘ runNondetJoinT ∘ runWriterT where ff ∷ [(a,o)] → ([a],o) ff asL = (fst ^$ asL,concat $ snd ^$ asL) nondetJoinWriterCommute ∷ ∀ o m. (Functor m) ⇒ NondetJoinT (WriterT o m) ↝ WriterT o (NondetJoinT m) nondetJoinWriterCommute = WriterT ∘ NondetJoinT ∘ (lazySet ∘ ff ∘ mapFst list) ^∘ runWriterT ∘ runNondetJoinT where ff ∷ ([a],o) → [(a,o)] ff (xs,o) = (,o) ^$ xs instance (Functor m,MonadWriter o m,Monoid o) ⇒ MonadWriter o (NondetJoinT m) where writerE ∷ WriterT o (NondetJoinT m) ↝ NondetJoinT m writerE = fmap writerE ∘ writerNondetJoinCommute writerI ∷ NondetJoinT m ↝ WriterT o (NondetJoinT m) writerI = nondetJoinWriterCommute ∘ fmap writerI instance (Functor m,MonadNondetJoin m,Monoid o) ⇒ MonadNondetJoin (WriterT o m) where nondetJoinE ∷ NondetJoinT (WriterT o m) ↝ WriterT o m nondetJoinE = fmap nondetJoinE ∘ nondetJoinWriterCommute nondetJoinI ∷ WriterT o m ↝ NondetJoinT (WriterT o m) nondetJoinI = writerNondetJoinCommute ∘ fmap nondetJoinI -- TODO: FlowAppendT -- ## Writer // Cont -- TODO -- ## Writer // OpaqeuCont -- TODO -- # State // * mergeState ∷ (Functor m) ⇒ StateT s₁ (StateT s₂ m) a → StateT (s₁,s₂) m a mergeState aMM = StateT $ \ (s₁,s₂) → ff ^$ runStateT (runStateT aMM s₁) s₂ where ff ∷ ((a,s₁),s₂) → (a,(s₁,s₂)) ff ((a,s₁),s₂) = (a,(s₁,s₂)) splitState ∷ (Functor m) ⇒ StateT (s₁,s₂) m a → StateT s₁ (StateT s₂ m) a splitState aM = StateT $ \ s₁ → StateT $ \ s₂ → ff ^$ runStateT aM (s₁,s₂) where ff ∷ (a,(s₁,s₂)) → ((a,s₁),s₂) ff (a,(s₁,s₂)) = ((a,s₁),s₂) mapState ∷ ∀ m s₁ s₂ a. (Functor m) ⇒ (s₁ ⇄ s₂) → StateT s₁ m a → StateT s₂ m a mapState iso aM = StateT $ \ s₂ → ff ^$ runStateT aM $ isoFrom iso s₂ where ff ∷ (a,s₁) → (a,s₂) ff (a,s₁) = (a,isoTo iso s₁) -- combineStateE ∷ (Functor m,MonadState s₂ (t m)) ⇒ s₃ ⇄ (s₁,s₂) → StateT s₃ (StateT s₁ m) ↝ (StateT s₁ m) -- combineStateE iso = stateE ∘ fmap stateE ∘ splitState ∘ mapState iso -- combineStateI ∷ (Functor m,MonadState s₁ m,MonadState s₂ m) ⇒ s₃ ⇄ (s₁,s₂) → m ↝ StateT s₃ m -- combineStateI iso = mapState (sym iso) ∘ mergeState ∘ fmap stateI ∘ stateI -- stateECombineFlowJoin -- ∷ (Functor m,MonadState s₁ m,MonadFlowJoin s₂ m) -- ⇒ (s₃ → (s₁,s₂)) -- → ((s₁,s₂) → s₃) -- → StateT s₃ m ↝ m -- stateECombineFlowJoin to from = -- stateE -- ∘ fmap (flowJoinE ∘ flowFromStateJ) -- ∘ splitState -- ∘ mapStateT to from -- ## State // Nondet [ADJ] stateNondetAppendCommute ∷ ∀ s m. (Functor m,Monoid s) ⇒ StateT s (NondetAppendT m) ↝ NondetAppendT (StateT s m) stateNondetAppendCommute aMM = NondetAppendT $ StateT $ \ s → ff ^$ runNondetAppendT $ runStateTWith s aMM where ff ∷ [(a,s)] → ([a],s) ff asL = (fst ^$ asL,concat $ snd ^$ asL) nondetAppendStateCommute ∷ ∀ s m. (Functor m) ⇒ NondetAppendT (StateT s m) ↝ StateT s (NondetAppendT m) nondetAppendStateCommute aMM = StateT $ \ s → NondetAppendT $ ff ^$ runStateTWith s $ runNondetAppendT aMM where ff ∷ ([a],s) → [(a,s)] ff (xs,s) = (,s) ^$ xs instance (Functor m,MonadState s m,Monoid s) ⇒ MonadState s (NondetAppendT m) where stateE ∷ StateT s (NondetAppendT m) ↝ NondetAppendT m stateE = fmap stateE ∘ stateNondetAppendCommute stateI ∷ NondetAppendT m ↝ StateT s (NondetAppendT m) stateI = nondetAppendStateCommute ∘ fmap stateI instance (Functor m,MonadNondetAppend m,Monoid s) ⇒ MonadNondetAppend (StateT s m) where nondetAppendE ∷ NondetAppendT (StateT s m) ↝ StateT s m nondetAppendE = fmap nondetAppendE ∘ nondetAppendStateCommute nondetAppendI ∷ StateT s m ↝ NondetAppendT (StateT s m) nondetAppendI = stateNondetAppendCommute ∘ fmap nondetAppendI stateNondetJoinCommute ∷ ∀ s m. (Functor m,JoinLattice s) ⇒ StateT s (NondetJoinT m) ↝ NondetJoinT (StateT s m) stateNondetJoinCommute aMM = NondetJoinT $ StateT $ \ s → (mapFst lazySet ∘ ff ∘ list) ^$ runNondetJoinT $ runStateTWith s aMM where ff ∷ [(a,s)] → ([a],s) ff asL = (fst ^$ asL,joins $ snd ^$ asL) nondetJoinStateCommute ∷ ∀ s m. (Functor m) ⇒ NondetJoinT (StateT s m) ↝ StateT s (NondetJoinT m) nondetJoinStateCommute aMM = StateT $ \ s → NondetJoinT $ (lazySet ∘ ff ∘ mapFst list) ^$ runStateTWith s $ runNondetJoinT aMM where ff ∷ ([a],s) → [(a,s)] ff (xs,s) = (,s) ^$ xs instance (Functor m,MonadState s m,JoinLattice s) ⇒ MonadState s (NondetJoinT m) where stateE ∷ StateT s (NondetJoinT m) ↝ NondetJoinT m stateE = fmap stateE ∘ stateNondetJoinCommute stateI ∷ NondetJoinT m ↝ StateT s (NondetJoinT m) stateI = nondetJoinStateCommute ∘ fmap stateI instance (Functor m,MonadNondetJoin m,JoinLattice s) ⇒ MonadNondetJoin (StateT s m) where nondetJoinE ∷ NondetJoinT (StateT s m) ↝ StateT s m nondetJoinE = fmap nondetJoinE ∘ nondetJoinStateCommute nondetJoinI ∷ StateT s m ↝ NondetJoinT (StateT s m) nondetJoinI = stateNondetJoinCommute ∘ fmap nondetJoinI -- ## State // Flow [ADJ] stateFlowAppendCommute ∷ ∀ s₁ s₂ m. (Functor m,Monoid s₁) ⇒ StateT s₁ (FlowAppendT s₂ m) ↝ FlowAppendT s₂ (StateT s₁ m) stateFlowAppendCommute xMM = FlowAppendT $ \ s₂ → StateT $ \ s₁ → ff ^$ runFlowAppendT (runStateT xMM s₁) s₂ where ff ∷ ((a,s₁) ⇰♭⧺ s₂) → (a ⇰♭⧺ s₂,s₁) ff xs₁s₂s = let ((xs,s₁s),s₂s) = mapFst unzip $ unzip $ list xs₁s₂s in (lazyDictAppend $ zipAssumeSameLength xs s₂s,concat s₁s) flowAppendStateCommute ∷ ∀ s₁ s₂ m. (Functor m,Monoid s₁) ⇒ FlowAppendT s₁ (StateT s₂ m) ↝ StateT s₂ (FlowAppendT s₁ m) flowAppendStateCommute xMM = StateT $ \ s₂ → FlowAppendT $ \ s₁ → ff ^$ runStateT (runFlowAppendT xMM s₁) s₂ where ff ∷ (a ⇰♭⧺ s₁,s₂) → ((a,s₂) ⇰♭⧺ s₁) ff (xs₁s,s₂) = lazyDictAppend $ map (mapFst (,s₂)) $ list xs₁s -- instance (Functor m,MonadState s m,Monoid s,Monoid s') ⇒ MonadState s (FlowAppendT s' m) where -- stateE ∷ StateT s (FlowAppendT s' m) ↝ FlowAppendT s' m -- stateE = fmap stateE ∘ stateFlowAppendCommute -- stateI ∷ FlowAppendT s' m ↝ StateT s (FlowAppendT s' m) -- stateI = flowAppendStateCommute ∘ fmap stateI -- -- instance (Functor m,MonadFlowAppend s m,Monoid s,Monoid s') ⇒ MonadFlowAppend s (StateT s' m) where -- flowAppendE ∷ FlowAppendT s (StateT s' m) ↝ StateT s' m -- flowAppendE = fmap flowAppendE ∘ flowAppendStateCommute -- flowAppendI ∷ StateT s' m ↝ FlowAppendT s (StateT s' m) -- flowAppendI = stateFlowAppendCommute ∘ fmap flowAppendI stateFlowJoinCommute ∷ ∀ s₁ s₂ m. (Functor m,JoinLattice s₁) ⇒ StateT s₁ (FlowJoinT s₂ m) ↝ FlowJoinT s₂ (StateT s₁ m) stateFlowJoinCommute xMM = FlowJoinT $ \ s₂ → StateT $ \ s₁ → ff ^$ runFlowJoinT (runStateT xMM s₁) s₂ where ff ∷ ((a,s₁) ⇰♭⊔ s₂) → (a ⇰♭⊔ s₂,s₁) ff xs₁s₂s = let ((xs,s₁s),s₂s) = mapFst unzip $ unzip $ list $ runLazyDictJoin xs₁s₂s in (lazyDictJoin $ zipAssumeSameLength xs s₂s,joins s₁s) flowJoinStateCommute ∷ ∀ s₁ s₂ m. (Functor m,JoinLattice s₁) ⇒ FlowJoinT s₁ (StateT s₂ m) ↝ StateT s₂ (FlowJoinT s₁ m) flowJoinStateCommute xMM = StateT $ \ s₂ → FlowJoinT $ \ s₁ → ff ^$ runStateT (runFlowJoinT xMM s₁) s₂ where ff ∷ (a ⇰♭⊔ s₁,s₂) → ((a,s₂) ⇰♭⊔ s₁) ff (xs₁s,s₂) = lazyDictJoin $ map (mapFst (,s₂)) $ list xs₁s -- instance (Functor m,MonadState s m,JoinLattice s,JoinLattice s') ⇒ MonadState s (FlowJoinT s' m) where -- stateE ∷ StateT s (FlowJoinT s' m) ↝ FlowJoinT s' m -- stateE = fmap stateE ∘ stateFlowJoinCommute -- stateI ∷ FlowJoinT s' m ↝ StateT s (FlowJoinT s' m) -- stateI = flowJoinStateCommute ∘ fmap stateI -- -- instance (Functor m,MonadFlowJoin s m,JoinLattice s,JoinLattice s') ⇒ MonadFlowJoin s (StateT s' m) where -- flowJoinE ∷ FlowJoinT s (StateT s' m) ↝ StateT s' m -- flowJoinE = fmap flowJoinE ∘ flowJoinStateCommute -- flowJoinI ∷ StateT s' m ↝ FlowJoinT s (StateT s' m) -- flowJoinI = stateFlowJoinCommute ∘ fmap flowJoinI -- ## State // Cont [???] stateKonCommute ∷ StateT s (ContT (r,s) m) ↝ ContT r (StateT s m) stateKonCommute aSK = ContT $ \ (k ∷ a → StateT s m r) → StateT $ \ s → runContT (runStateTWith s aSK) $ \ (a,s') → runStateTWith s' $ k a konStateCommute ∷ ContT r (StateT s m) ↝ StateT s (ContT (r,s) m) konStateCommute aKS = StateT $ \ s → ContT $ \ (k ∷ (a,s) → m (r,s)) → runStateTWith s $ runContT aKS $ \ a → StateT $ \ s' → k (a,s') instance (Monad m,MonadState s m) ⇒ MonadState s (ContT r m) where stateE ∷ StateT s (ContT r m) ↝ ContT r m stateE = fisomap (stateE,stateI) ∘ stateKonCommute ∘ stateE ∘ fmap (konStateCommute ∘ fisomap (stateI,stateE ∷ StateT s m ↝ m)) stateI ∷ ContT r m ↝ StateT s (ContT r m) stateI = fmap (fisomap (stateE,stateI) ∘ stateKonCommute) ∘ stateI ∘ konStateCommute ∘ fisomap (stateI,stateE ∷ StateT s m ↝ m) -- # State // OpaqueCont [???] instance (Monad m,MonadState s m,Isomorphic3 (ContFun r) (k r)) ⇒ MonadState s (OpaqueContT k r m) where stateE ∷ StateT s (OpaqueContT k r m) ↝ OpaqueContT k r m stateE = opaque ∘ stateE ∘ fmap meta stateI ∷ OpaqueContT k r m ↝ StateT s (OpaqueContT k r m) stateI = fmap opaque ∘ stateI ∘ meta --------- -- RWS -- --------- newtype RWST r o s m a = RWST { runRWST ∷ ReaderT r (WriterT o (StateT s m)) a } deriving ( Functor,Monad , MonadFailure , MonadError e , MonadReader r , MonadWriter o , MonadState s ) runRWSTWith ∷ ∀ r o s m a. (Functor m) ⇒ r → s → RWST r o s m a → m (a,o,s) runRWSTWith r s₀ aM = ff ^$ runStateTWith s₀ $ runWriterT $ runReaderTWith r $ runRWST aM where ff ∷ ((a,o),s) → (a,o,s) ff ((a,o),s) = (a,o,s) -- Base Effect type RWS r o s = RWST r o s ID runRWSWith ∷ r → s → RWS r o s a → (a,o,s) runRWSWith r s aM = runID $ runRWSTWith r s aM -- Higher Functor instance FunctorFunctor (RWST r o s) where fmap ∷ (m ↝ n) → RWST r o s m a → RWST r o s n a fmap f = RWST ∘ fmap (fmap (fmap f)) ∘ runRWST -- -------------------- -- -- Adding Effects -- -- -------------------- -- -- -- # AddWriterT -- -- newtype AddWriterT o₁₂ o₁ m a = AddWriterT { runAddWriterT ∷ WriterT o₁ m a } -- deriving -- ( Functor,Monad -- , MonadMonoid,MonadBot,MonadJoin -- , MonadFailure -- , MonadError e -- , MonadReader r -- , MonadState s -- -- TODO: implement -- -- , MonadCont r -- -- TODO: implement and role annotation -- -- , MonadOpaqueCont k r -- ) -- -- mergeWriter ∷ (Functor m) ⇒ WriterT o₁ (WriterT o₂ m) a → WriterT (o₁,o₂) m a -- mergeWriter = WriterT ∘ ff ^∘ runWriterT ∘ runWriterT -- where -- ff ∷ ((a,o₁),o₂) → (a,(o₁,o₂)) -- ff ((a,o₁),o₂) = (a,(o₁,o₂)) -- -- splitWriter ∷ (Functor m) ⇒ WriterT (o₁,o₂) m a → WriterT o₁ (WriterT o₂ m) a -- splitWriter = WriterT ∘ WriterT ∘ ff ^∘ runWriterT -- where -- ff ∷ (a,(o₁,o₂)) → ((a,o₁),o₂) -- ff (a,(o₁,o₂)) = ((a,o₁),o₂) -- -- instance (Functor m,MonadWriter o₂ m,Monoid o₁,Isomorphism o₁₂ (o₁,o₂)) ⇒ MonadWriter o₁₂ (AddWriterT o₁₂ o₁ m) where -- writerI ∷ AddWriterT o₁₂ o₁ m ↝ WriterT o₁₂ (AddWriterT o₁₂ o₁ m) -- writerI = -- fmap AddWriterT -- ∘ mapOutput isoFrom -- ∘ mergeWriter -- ∘ fmap (writerCommute ∘ fmap writerI) -- ∘ writerI -- ∘ runAddWriterT -- writerE ∷ WriterT o₁₂ (AddWriterT o₁₂ o₁ m) ↝ AddWriterT o₁₂ o₁ m -- writerE = -- AddWriterT -- ∘ writerE -- ∘ fmap (fmap writerE ∘ writerCommute) -- ∘ splitWriter -- ∘ mapOutput isoTo -- ∘ fmap runAddWriterT -- -- -- # AddStateT -- -- newtype AddStateT s₁₂ s₁ m a = AddStateT { runAddStateT ∷ StateT s₁ m a } -- deriving -- ( Functor,Monad -- , MonadMonoid,MonadBot,MonadJoin -- , MonadFailure -- , MonadError e -- , MonadReader r -- , MonadWriter o -- -- TODO: implement -- -- , MonadCont r -- -- TODO: implement -- -- , MonadOpaqueCont k r -- ) -- -- instance (Functor m,MonadState s₂ m,Isomorphism s₁₂ (s₁,s₂)) ⇒ MonadState s₁₂ (AddStateT s₁₂ s₁ m) where -- stateI ∷ AddStateT s₁₂ s₁ m ↝ StateT s₁₂ (AddStateT s₁₂ s₁ m) -- stateI = -- fmap AddStateT -- ∘ mapStateT isoFrom isoTo -- ∘ mergeState -- ∘ fmap (stateCommute ∘ fmap stateI) -- ∘ stateI -- ∘ runAddStateT -- stateE ∷ StateT s₁₂ (AddStateT s₁₂ s₁ m) ↝ AddStateT s₁₂ s₁ m -- stateE = -- AddStateT -- ∘ stateE -- ∘ fmap (fmap stateE ∘ stateCommute) -- ∘ splitState -- ∘ mapStateT isoTo isoFrom -- ∘ fmap runAddStateT