For example, MaybeT
is defined as:
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a)}
But not:
newtype MaybeT m a =
MaybeT { runMaybeT :: Maybe (m a) }
Why is this?
Monad transformers not only make it easier to write getPassphrase but also simplify all the code instances.
A Monad that can convert any given IO[A] into a F[A] , useful for defining parametric signatures and composing monad transformer stacks.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
Looking at StateT
might be instructive:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
Here the state is neither "inner" nor "outer", but its type is interleaved with the monad it is transforming, some bits inside, some outside. And indeed
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
is all "outer". So it depends on what transformer it is. There's probably some category theory that at least partially explains this interleaving, I'm curious to know about it (intelligentsia?).
Contrast with applicative functors, for which
newtype Compose f g a = Compose { getCompose :: f (g a) }
is an applicative as well, so there is always a clear "inner/outer" relationship. You could make an applicative-only StateT
, and finding its structure by Compose (State s)
:
ApplicativeStateT s f a = s -> (s, f a)
In fact, there's another one if you compose on the right:
ApplicativeStateT' s f a = f (s -> (s,a))
But monads have no such regularity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With