Difference between revisions of "Incompatibilities between MTL 1 and MTL 2"
(Introductory paragraph) |
m (Reverted edits by Tomjaguarpaw (talk) to last revision by YitzGale) |
||
(2 intermediate revisions by 2 users not shown) | |||
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 15:19, 6 February 2021
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
andAlternative
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 requireMonad
whereFunctor
is sufficient. Unfortunately this is incompatible becauseFunctor
is not a superclass ofMonad
, 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.