test-monad-laws-0.0.0.0: src/Test/Monad/State/Mutants.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Test.Monad.State.Mutants where
import Control.Monad.State
import Data.Functor.Identity
import Test.QuickCheck.HigherOrder (Equation(..))
import Test.Mutants
bad_get_put_get :: forall m s. MonadState s m => s -> Equation (m s)
bad_get_put_get s = (put s >> get) :=: (get >>= \s' -> put s >> return @m s')
bad_put_put :: forall m s. MonadState s m => s -> s -> Equation (m ())
bad_put_put s1 s2 = (put s1 >> put s2) :=: put @_ @m s1
-- * 'StateT' mutant
-- Can't get 'get' wrong.
-- Only one way to get 'put' wrong.
--
-- Parametricity!
data PutDoesNothing
-- | Fails:
--
-- > 'put_get'
--
-- Passes (wrongly):
--
-- > 'bad_get_put_get'
-- > 'bad_put_put'
type MutantStateT s = Mutant PutDoesNothing (StateT s)
type MutantState s = MutantStateT s Identity
instance {-# OVERLAPPING #-}
Monad m => MonadState s (MutantStateT s m) where
get = Mutant get
put _s = Mutant $ StateT $ \s -> return ((), s) -- "oops"