{-# LANGUAGE FlexibleInstances #-} module Test.Monad.Trans.Mutants where import Control.Monad.Trans import Control.Monad.Trans.Maybe import Data.Functor (($>)) import Test.Mutants -- | An general way to get 'MonadTrans' wrong is to run the base -- computation twice. data LiftTwice instance {-# OVERLAPPING #-} MonadTrans t => MonadTrans (Mutant LiftTwice t) where lift m = lift (m >> m) -- Other kinds of mistakes are difficult to make, by parametricity. -- State: -- lift :: m a -> (s -> m (a, s)) -- Except: -- lift :: m a -> m (Either e a) -- Writer: -- lift :: m a -> m (w, a) -- Reader: -- lift :: m a -> (r -> m a) -- Maybe: -- lift :: m a -> m (Maybe a) -- | Forget the computation. data LiftMaybeNothing instance {-# OVERLAPPING #-} MonadTrans (Mutant LiftMaybeNothing MaybeT) where lift _ = Mutant . MaybeT $ return Nothing -- | Run the computation but forget the result. data LiftMaybeDiscard instance {-# OVERLAPPING #-} MonadTrans (Mutant LiftMaybeDiscard MaybeT) where lift m = Mutant . MaybeT $ m $> Nothing