Reputation: 1917
I read (for example here and here) that all of the base monads
(Mabye
, Error
, ...) are derived from their corresponding monad transformers
(MaybeT
, ErrorT
, ...) using the identity monad Identity
. An example would be:
type Maybe a = MaybeT Identity a
But that of course doesn't result in a constructor for Maybe a
.
And in the sources MaybeT
is defined as newtype MaybeT m a = MaybeT (m (Maybe a))
.
Am I missing something important?
How could one derive a base monad using the corresponding monad transformer and the identitiy monad resulting in a concrete
constructor that can be matched against?
Upvotes: 3
Views: 220
Reputation: 116139
Different approaches are being used here.
Sometimes, the base monad Foo
is defined in terms of its transformer as FooT Identity
. For example, State
from transformer package, as Daniel Wagner points out.
Other times, the base monad Foo
is defined independently. In these cases, it usually happens that Foo
and FooT Indentity
are distinct types, which however are isomorphic. This means that you can convert between both types without losing any information.
I guess that since Maybe
is defined in the Haskell report as a Prelude
type, we can not easily redefine it as the isomorphic MaybeT Identity
. Indeed, since it's common to destruct/eliminate values in Maybe a
by pattern matching against Nothing
and Just _
, we can't use another definition. If we had user-definable patterns we could use pattern Just x = Module.Just (Identity x)
, but we have not these (for now).
Instead, other monads such as State
are not in the Prelude
, nor in the Haskell report. They are also not typically destructed via pattern matching by whomever is importing Control.Monad.State
. In such cases, it felt less harmful to move to the StateT Identity
variant.
Upvotes: 3
Reputation: 21811
The Maybe
monad is not defined as MaybeT Identity a
for backwards compatibility, since Maybe
was part of GHC long before MaybeT
.
You are correct that using a monad transformer with Identity
would not result in a type constructor that can be matched on. Fortunately, I've never had to pattern match on monad constructors when using the monad transformer paradigm. Instead, you can use do
notation and monad operations (liftM
, runReaderT
, etc).
Upvotes: 2