Refactoring the MTL
Ganesh and Ross propose that the next version of the mtl package should be a compatibility layer over the transformers and monads-fd packages. A draft of this compatibility layer is available at http://urchin.earth.li/darcs/ganesh/mtl-compat .
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.
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 sare now aliases for
StateT s Identity.
- Functor instances for monad transformers no longer require Monad where Functor is sufficient.
- instances of
Alternativehave been added as appropriate.
- simple monads like
- This package can be used on its own, or with packages adding type classes.
- monads-fd depends on transformers and adds type classes using functional dependencies.
- 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.
- 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.State.Class, where code using the mtl would have to import just
- The module
Control.Monad.Cont.Classis Haskell 98. Should it be moved out of monads-fd, and if so where?
A survey of Hackage in March 2009 found 19 packages that would fail to compile with the proposed new version of mtl. 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 0.5.1.1 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)