ClassLaws-0.3.0.0: src/Control/Monad/Laws/Instances.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
-- | Tests the Monad ClassLaws for a few example datatypes. Mainly
-- instance declarations and QuickCheck tests + a 'main' to run it.
module Control.Monad.Laws.Instances where
import Control.Monad.State
import Control.Monad.Laws
import Test.ClassLaws
import Test.ClassLaws.TestingDatatypes(MyList(..), (+++), snoc, foldrMyList)
instance FunctorLaws [] where
functorLaw1 xs = addSteps (defaultFunctorLaw1 xs)
(case xs of
[] -> nilCase
ys@(_:_) -> conCase ys)
where
nilCase =
[ fmap id []
, -- definition of fmap on []
[]
]
conCase (y:ys) =
[ fmap id (y:ys)
, -- definition of fmap on (x:xs)
id y:fmap id ys
, -- definition of id
y:fmap id ys
-- y:fmap id (ys++ys) -- gives an error (used to test error injection)
, -- induction hypothesis
y:ys
, -- definition of id
id (y:ys)
]
testFunctorList
= do quickLawCheck (undefined::FunctorLaw1 Char [])
quickFLawCheck (undefined::FunctorLaw2 Int Char Bool [])
instance FunctorLaws Maybe
testFunctorMaybe
= do quickLawCheck (undefined::FunctorLaw1 Char Maybe)
quickFLawCheck (undefined::FunctorLaw2 Int Char Bool Maybe)
instance FunctorLaws IO
{- -- How do I test IO values?
testFunctorIO
= do quickBlind (undefined::FunctorLaw1 Char IO)
quickBlind (undefined::FunctorLaw2 Int Char Bool IO)
-}
{-
The following instance of Functor for MyList should *not* satisfy the functor
laws.
-}
-- Wrong instance of functor, because the order is reversed by fmap.
instance Functor MyList where
fmap f Nil = Nil
fmap f (Cons x xs) = snoc (f x) (fmap f xs)
instance FunctorLaws MyList
where
functorLaw1 xs = addSteps (defaultFunctorLaw1 xs)
(case xs of
Nil -> nilCase
zs@(Cons y ys) -> conCase zs)
where
nilCase =
[ fmap id Nil
, -- definition of fmap on []
Nil
]
conCase (Cons y ys) =
[ fmap id (Cons y ys)
, -- definition of fmap on (x:xs)
snoc (id y) (fmap id ys)
, -- definition of id
snoc y (fmap id ys)
, -- induction hypothesis
snoc y ys
, -- definition of id
id (Cons y ys)
]
testFunctorMyList
= do quickLawCheck (undefined::FunctorLaw1 Int MyList)
quickFLawCheck (undefined::FunctorLaw2 Char Int Int MyList)
instance MonadLaws []
testMonadList
= do quickFLawCheck (undefined::MonadLaw1 Char Int [])
quickLawCheck (undefined::MonadLaw2 Int [])
quickFLawCheck (undefined::MonadLaw3 Int Bool Char [])
instance MonadLaws Maybe
testMonadMaybe
= do quickFLawCheck (undefined::MonadLaw1 Char Int Maybe)
quickLawCheck (undefined::MonadLaw2 Int Maybe)
quickFLawCheck (undefined::MonadLaw3 Int Bool Char Maybe)
instance FunctorMonadLaws MyList
testFunctorMonadMyList
= do quickFLawCheck (undefined:: FunctorMonadLaw Char Int MyList)
instance MonadLaws IO
instance MonadLaws (State s)
testMonadState
= do quickFLawCheck (undefined::MonadLaw1 Bool Int (State Bool))
quickFLawCheck (undefined::MonadLaw2 Int (State Bool)) -- necessary because of Show State problem
quickFLawCheck (undefined::MonadLaw3 Int Bool Char (State Bool))
instance Monad MyList where
m >>= k = foldrMyList ((+++) . k) Nil m
m >> k = foldrMyList ((+++) . (\ _ -> k)) Nil m
return x = Cons x (Cons x Nil) -- gives an error
-- return x = Cons x Nil -- correct
fail _ = Nil
instance MonadLaws MyList
testMonadMyList
= do quickFLawCheck (undefined::MonadLaw1 Char Int MyList)
quickLawCheck (undefined::MonadLaw2 Int MyList)
quickFLawCheck (undefined::MonadLaw3 Int Bool Char MyList)
instance FunctorMonadLaws []
testFunctorMonadList
= do quickFLawCheck (undefined::FunctorMonadLaw Char Int [])
instance FunctorMonadLaws Maybe
testFunctorMonadMaybe
= do quickFLawCheck (undefined::FunctorMonadLaw Char Int Maybe)
instance FunctorMonadLaws IO
main = do testMonadMaybe
testMonadState
testFunctorList
testFunctorMaybe
testFunctorMonadList
testFunctorMonadMaybe
expectedFailures = do
testMonadMyList
testFunctorMyList
testFunctorMonadMyList
-- No MonadPlusLaw instances yet.