Incompatibilities between MTL 1 and MTL 2

From HaskellWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Version 2 of the Monad Transformer Library introduced some small incompatibilities relative to version 1, described below. See "Upgrading from MTL 1 to MTL 2" for instructions on how to make code written for version 1 work with version 2.

The interface of mtl-2 is close to that of mtl-1, but with the following differences (illustrated with Reader):

  • Instances of Applicative and Alternative have been added as appropriate, e.g.
instance (Applicative m) => Applicative (ReaderT r m) where ...
instance (Alternative m) => Alternative (ReaderT r m) where ...

Rationale: These classes postdate the MTL, and such instances have been repeatedly defined in various packages. They belong together with the type constructors.

  • Functor instances for monad transformers no longer require Monad where Functor is sufficient. Unfortunately this is incompatible because Functor is not a superclass of Monad, e.g.
instance (Monad m) => Functor (ReaderT r m) where ...
is replaced by
instance (Functor m) => Functor (ReaderT r m) where ...

Rationale: These instances are more general, and are consistent with the instances of other classes.

  • Simple monads are now aliases for monad trasformers applied to Identity, e.g.
newtype Reader r a = Reader { runReader :: r -> a }
is replaced by
type Reader r = ReaderT r Identity
 
reader :: (r -> a) -> Reader r a
reader f = ReaderT (Identity . f)

runReader :: Reader r a -> r -> a
runReader m = runIdentity . runReaderT m

Rationale: This avoids repetition in the interfaces of both transformers and mtl-2. It makes transformers more useful on its own, and also saves clients of mtl from defining instances for both Reader r and ReaderT r and ensuring that they are consistent.

  • The instance Error String is restructured to avoid a type synonym instance:
instance Error String where
    noMsg  = ""
    strMsg = id
  is replaced by
instance ErrorList a => Error [a] where
    strMsg = listMsg
 
class ErrorList a where
    listMsg :: String -> [a]
 
instance ErrorList Char where
    listMsg = id

Rationale: This makes the instance Haskell 98, so it can be included in the transformers package.