Tidying up Monads - turning application of a monad transformer into newtype monad

jakubdaniel

I am trying to take e.g. ExceptT a (StateT A M), for some concrete type A and monad M, and wrap them up into my new custom monads.

First I identified that StateT A M appears often in other contexts and thus I decided it would be best to wrap that alone in a monad M1 and then wrap ExceptT a M1 into M2.

The desired property is to make M1 and M2 instances of MonadState and the class of M (lets assume it is called MyMonadClass). Also M2 should be an instance of MonadError.

First I started by simple type synonyms:

type MyState    = StateT A M
type MyBranch a = ExceptT a MyState

then I thought that I would first sketch the instance declarations (without implementing the instance) and thats where I first got stuck. instance MonadState A (MyState) seemed to not be the right syntax. I thought I would have to create newtype MyState' a = StateT a M and then type MyState = MyState A (Lets not use language extensions where not necessary).

However once I started converting the synonyms into newtype declarations I started to lose the connection to the StateT A M and ExceptT ... types.

newtype MyState' s a = MyState' { runMyState :: s -> (s, a) }
type MyState = MyState' A
newtype MyBranch e a = MyBranch { runMyBranch :: MyState (Either e a) }

Now the transformers that are already implemented disappeared and I think I am trying to do something that does not make much sense. So my question is: How would one correctly wrap this kind of behaviour into new compound monads that make accessible the layers underneath so that one avoids unnecessary lifting and keeps things clear and well-organized.

Cirdec

The normal pattern is to define a newtype for your complete transformer stack.

data A = A
data E = E

newtype MyBranchT m a = MyBranchT { getMyBranchT :: ExceptT E (StateT A m) a }

If there are any pieces of the stack that add meaningful new capabilities on their own you'd also define newtypes for those pieces.

Then you use GeneralizedNewtypeDeriving to get instances for all of the various monad classes.

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

-- base
import Control.Applicative
import Control.Monad

-- transformers
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Except
import Control.Monad.Trans.State.Lazy

-- mtl classes
import Control.Monad.Cont.Class
import Control.Monad.Error.Class
import Control.Monad.Reader.Class
import Control.Monad.State.Class
import Control.Monad.Writer.Class

data A = A
data E = E

newtype MyBranchT m a = MyBranchT { getMyBranchT :: ExceptT E (StateT A m) a }
    deriving (Functor, Applicative, Monad, MonadIO,     -- classes from base and transformers
              {- Alternative, MonadPlus, -}             -- if E is a monoid
              MonadState A, MonadError E,               -- classes from mtl that MyBranchT provides
              MonadCont, MonadReader r, MonadWriter w)  -- classes from mtl that might be available from m

You'll have to write the MonadTrans instance by hand. lift is always just lift once for each of the transformers in the stack.

instance MonadTrans MyBranchT where
    lift = MyBranchT . lift . lift

If there are any pieces of the stack that add meaningful new capabilities X on their own you'd also define a new MonadX class for those capabilities, write MonadX instances for each of the monad transfomers (StateT, ExceptT, ContT, etc) if possible, and derive the MonadX instance for your transformer stack (MyBranchT).

You'll also usually make a type synonym for MyBranchT Identity and functions to runMyBranchT and runMyBranch

import Data.Functor.Identity

type MyBranch a = MyBranchT Identity a

runMyBranchT :: MyBranchT m a -> A -> m (Either E a, A)
runMyBranchT mb s = runStateT (runExceptT (getMyBranchT mb)) s

runMyBranch :: MyBranch a -> A -> (Either E a, A)
runMyBranch mb s = runIdentity $ runMyBranchT mb s

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Haskell: Monads of monad

From Dev

Defining Monad of nested monads

From Java

Is there a valid array monad transformer?

From Java

How is Kleisli a monad Transformer?

From Dev

Stacking ResourceT monad transformer

From Dev

WriterT monad transformer

From Dev

Monad Transformer stacks in Scala

From Dev

Deriving a base monad using a monad transformer and the identity monad

From Dev

Unwrapping the STT monad in a transformer stack?

From Dev

Monad Transformer stacks with MaybeT and RandT

From Dev

Working with monad transformer RWST in Haskell

From Dev

Why are monad transformers different to stacking monads?

From Dev

Use list monad inside monad transformer type classes?

From Dev

Adding a monad transformer to the Yesod Handler stack

From Dev

How to get ReaderT to work with another monad transformer?

From Dev

Converting a nested type into a monad transformer stack

From Dev

Scotty monad transformer for per-handler Reader

From Dev

Is there a library or typeclass for getting the transformer version of a monad?

From Dev

How to implement the `List` monad transformer in Scala?

From Dev

Java 8 Generic of Generic for Monad Transformer

From Dev

How to refactor program that uses state monad transformer?

From Dev

MonadFix instance for interpreter monad transformer generated by FreeT?

From Dev

Defining bind for home-made monad transformer

From Dev

Tow definition of function "return" in monad transformer MaybeT

From Dev

Lift to fix the *inside* of a monad transformer stack

From Dev

How to implement the `List` monad transformer in Scala?

From Dev

How to get ReaderT to work with another monad transformer?

From Dev

Lift to fix the *inside* of a monad transformer stack

From Dev

Tow definition of function "return" in monad transformer MaybeT

Related Related

  1. 1

    Haskell: Monads of monad

  2. 2

    Defining Monad of nested monads

  3. 3

    Is there a valid array monad transformer?

  4. 4

    How is Kleisli a monad Transformer?

  5. 5

    Stacking ResourceT monad transformer

  6. 6

    WriterT monad transformer

  7. 7

    Monad Transformer stacks in Scala

  8. 8

    Deriving a base monad using a monad transformer and the identity monad

  9. 9

    Unwrapping the STT monad in a transformer stack?

  10. 10

    Monad Transformer stacks with MaybeT and RandT

  11. 11

    Working with monad transformer RWST in Haskell

  12. 12

    Why are monad transformers different to stacking monads?

  13. 13

    Use list monad inside monad transformer type classes?

  14. 14

    Adding a monad transformer to the Yesod Handler stack

  15. 15

    How to get ReaderT to work with another monad transformer?

  16. 16

    Converting a nested type into a monad transformer stack

  17. 17

    Scotty monad transformer for per-handler Reader

  18. 18

    Is there a library or typeclass for getting the transformer version of a monad?

  19. 19

    How to implement the `List` monad transformer in Scala?

  20. 20

    Java 8 Generic of Generic for Monad Transformer

  21. 21

    How to refactor program that uses state monad transformer?

  22. 22

    MonadFix instance for interpreter monad transformer generated by FreeT?

  23. 23

    Defining bind for home-made monad transformer

  24. 24

    Tow definition of function "return" in monad transformer MaybeT

  25. 25

    Lift to fix the *inside* of a monad transformer stack

  26. 26

    How to implement the `List` monad transformer in Scala?

  27. 27

    How to get ReaderT to work with another monad transformer?

  28. 28

    Lift to fix the *inside* of a monad transformer stack

  29. 29

    Tow definition of function "return" in monad transformer MaybeT

HotTag

Archive