Personal tools

Incompatibilities between MTL 1 and MTL 2

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
(Introductory paragraph)
 
(Added content from the Haskell Platform trac wiki)
 
Line 3: Line 3:
 
See "[[Upgrading from MTL 1 to MTL 2]]" for instructions on how
 
See "[[Upgrading from MTL 1 to MTL 2]]" for instructions on how
 
to make code written for version 1 work with version 2.
 
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 <hask>Reader</hask>):
  +
* Instances of <hask>Applicative</hask> and <hask>Alternative</hask> have been added as appropriate, e.g.
  +
<haskell>
  +
instance (Applicative m) => Applicative (ReaderT r m) where ...
  +
instance (Alternative m) => Alternative (ReaderT r m) where ...
  +
</haskell>
  +
  +
''Rationale:'' These classes postdate the MTL, and such instances have been repeatedly defined in various packages. They belong together with the type constructors.
  +
* <hask>Functor</hask> instances for monad transformers no longer require <hask>Monad</hask> where <hask>Functor</hask> is sufficient. Unfortunately this is incompatible because <hask>Functor</hask> is not a superclass of <hask>Monad</hask>, e.g.
  +
<haskell>
  +
instance (Monad m) => Functor (ReaderT r m) where ...
  +
</haskell>
  +
:is replaced by
  +
<haskell>
  +
instance (Functor m) => Functor (ReaderT r m) where ...
  +
</haskell>
  +
  +
''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 <hask>Identity</hask>, e.g.
  +
<haskell>
  +
newtype Reader r a = Reader { runReader :: r -> a }
  +
</haskell>
  +
:is replaced by
  +
<haskell>
  +
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
  +
</haskell>
  +
''Rationale:'' This avoids repetition in the interfaces of both
  +
[http://hackage.haskell.org/package/transformers transformers]
  +
and mtl-2. It makes transformers more useful on its own, and also saves clients of mtl from defining instances for both <hask>Reader r</hask> and <hask>ReaderT r</hask> and ensuring that they are consistent.
  +
* The instance <hask>Error String</hask> is restructured to avoid a type synonym instance:
  +
<haskell>
  +
instance Error String where
  +
noMsg = ""
  +
strMsg = id
  +
</haskell>
  +
is replaced by
  +
<haskell>
  +
instance ErrorList a => Error [a] where
  +
strMsg = listMsg
  +
  +
class ErrorList a where
  +
listMsg :: String -> [a]
  +
  +
instance ErrorList Char where
  +
listMsg = id
  +
</haskell>
  +
''Rationale:'' This makes the instance Haskell 98, so it can be included in the
  +
[http://hackage.haskell.org/package/transformers transformers]
  +
package.
   
 
[[Category:Monad]]
 
[[Category:Monad]]

Latest revision as of 12:05, 16 November 2010

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.