jules
jules

Reputation: 1917

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

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

Answers (2)

chi
chi

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

crockeea
crockeea

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

Related Questions