Version 1 (modified by ross, 5 years ago)

draft proposal

Refactoring the mtl package

The proposal is to add the transformers and monads-fd packages, and make the next version of the mtl package a compatibility layer over them. A draft of this compatibility layer is available at . This represents a restructuring of the mtl package.


Proposed by Ganesh Sittampalam (maintainer of the mtl compatibility layer) and Ross Paterson (maintainer of transformers and monads-fd). If this proposal is accepted, these packages would be turned over to community control (like the current mtl package).


Monad transformers are widely used, but the MTL implementation is tied to functional dependencies, whose future is in doubt. Many people want to try out versions based on type functions, or without using advanced type classes at all, but their interfaces will then be incompatible with libraries using mtl.

The idea is to factor out the monad transformers as a Haskell 98 package, which can be used by itself or with type classes based on either functional dependencies or type functions. Interfaces referring to the monad transformers would be compatible across the different libraries.

We would encourage clients to switch from mtl to either plain transformers or transformers + monads-fd, but would retain the mtl compatibility layer for the forseeable future.


The current mtl is to be replaced with three packages.

  • transformers is a Haskell 98 package containing the identity monad (Control.Monad.Identity), transformer classes (Control.Monad.Trans) and concrete monad transformers with code to lift operators (Control.Monad.Trans.*). There are also a number of changes in comparison with mtl:
    • simple monads like State s are now aliases for StateT s Identity.
    • Functor instances for monad transformers no longer require Monad where Functor is sufficient.
    • instances of Applicative and Alternative have been added as appropriate.

The package can be used on its own, or with packages adding type classes. There are examples of standalone use in the Control.Monad.Trans documentation.

  • monads-fd depends on transformers and adds type classes using functional dependencies. Usage is the same as the current mtl package, except for module names.
  • The new version of mtl depends on transformers and monads-fd, and is almost a compatible replacement for the current version, except for the differences listed above.

Open issues

  • The monads-fd and monads-tf packages use the same names for modules with different interfaces. Although monads-tf is not part of this proposal, should the modules in it or both the packages be renamed, and if so to what?
  • Should we delete all but the Class modules from monads-fd (and monads-tf)? That would mean that code using transformers and monads-fd directly would have to import both Control.Monad.Trans.State and Control.Monad.State.Class, where code using the mtl would have to import just Control.Monad.State.
  • The module Control.Monad.Cont.Class is Haskell 98. Should it be moved out of monads-fd, and if so where?
  • Both transformers and the new mtl would expose the modules Control.Identity and Control.Monad.Trans, though the mtl versions would be re-exports of the transformers modules. Thus people using ghc --make would still see conflicts. What to do?

Transition issues

A survey of Hackage in March 2009 found 19 packages that would fail to compile with the proposed new version of mtl. Note that this survey excluded packages that depend (directly or indirectly) on gtk2hs or any other packages not available on hackage. It also excluded packages that already declare an appropriate upper bound on their mtl dependency.

Those packages will need changes to compile with the new version of mtl, but need not switch to transformers and monads-fd (or just transformers) until later. These packages could add a dependency constraint mtl < 2 now, to avoid being built with the new version when it appears. The affected packages are listed below.

Different dependencies, extra instances:

  • blogination: Functor instances depending on Functor, instance collision Applicative/Alternative ErrorT
  • category-extras: Functor instances depending on Functor
  • cgi: Functor instances depending on Functor
  • encoding: instance collision: Monad Either
  • logict: instance collision: Applicative Identity (will be superfluous: same as instance in transformers)
  • monad-param: Functor instances depending on Functor
  • mueval: Functor instances depending on Functor
  • xcb-types: instance collision: Applicative/Alternative ReaderT (will be superfluous: same as instance in transformers; version has mtl < 1.2)
  • xmonad-contrib: instance collision: Error [a]:

Data constructors for basic monad classes:

  • FileManip: Missing data constructor: State
  • HAppS-Server: Missing data constructor: Reader
  • HaLeX: Missing data constructor: State
  • LambdaHack: Missing data constructor: State (version 0.1.20090606 has mtl < 2)
  • lambdabot: Missing data constructor: State
  • open-witness: Missing data constructor: State

Instances for basic monad classes that are now type synonyms:

  • applicative-extras: instance Applicative (State a) (will be superfluous: same as instance in transformers)
  • derive: instance Applicative (Writer a) (will be superfluous: same as instance in transformers)
  • random-fu: instance MonadRandom? (State StdGen?) (will be superfluous: same instance as declared for StateT)
  • yhccore: instance UniqueIdM (State a) (could be trivially generalized to StateT)