module Data.Monoid.Laws.Instances where
import Data.Monoid (Monoid(mappend, mempty), Endo(Endo), appEndo)
import Data.Monoid.Laws (MonoidLaws(..), MonoidLaw1, MonoidLaw2, MonoidLaw3)
import Test.ClassLaws ( Equal, Law, quickLawCheck, lawtest, Property, quickCheck
, Partial(Partial), unPartial
, ArbitraryPartial(arbitraryPartial), SemanticEq((==!), semanticEq), SemanticOrd
, quickLawCheckPartial
)
import Test.ClassLaws.TestingDatatypes (MyList(..), (+++))
import Test.ClassLaws.TestingFinFuns(arbitraryPartialFun, showPartialFun, eqPartial, semEqFun)
import Control.Monad (liftM)
import Data.List(intersperse)
instance MonoidLaws (Endo a)
instance Show (Endo Int) where
show (Endo f) = "E("++(concat $ intersperse "," $ map (show . f) [0..10])++")"
testMonoidEndo =
do quickLawCheck (undefined::MonoidLaw1 (Endo Bool))
quickLawCheck (undefined::MonoidLaw2 (Endo Bool))
quickLawCheck (undefined::MonoidLaw3 (Endo Bool))
instance (Bounded a, Enum a, Show (Partial a)) => Show (Partial (Endo a)) where
show (Partial (Endo e)) = showPartialFun e
instance (Bounded a, Enum a, SemanticOrd a,
ArbitraryPartial a) => ArbitraryPartial (Endo a) where
arbitraryPartial = liftM Endo (arbitraryPartialFun arbitraryPartial)
instance (Bounded a, Enum a, Eq a) => Eq (Endo a) where
(Endo f) == (Endo g) = f == g
instance (Bounded a, Enum a, SemanticEq a) => SemanticEq (Endo a) where
semanticEq tweak (Endo f) (Endo g) = semEqFun semanticEq tweak f g
testMonoidEndoPartial = do
quickLawCheckPartial (undefined::MonoidLaw1 (Endo Bool))
quickLawCheckPartial (undefined::MonoidLaw2 (Endo Bool))
quickLawCheckPartial (undefined::MonoidLaw3 (Endo Bool))
instance Monoid (MyList a) where
mempty = Nil
mappend xs ys = xs +++ ys +++ xs
instance MonoidLaws (MyList a)
testMonoidMyList =
do quickLawCheck (undefined :: MonoidLaw1 (MyList Int))
quickLawCheck (undefined :: MonoidLaw2 (MyList Int))
quickLawCheck (undefined :: MonoidLaw3 (MyList Int))
main = do testMonoidEndo
testMonoidMyList
instance Bounded (Endo Bool) where
minBound = Endo (const False)
maxBound = Endo (const True)
instance Enum (Endo Bool) where
fromEnum (Endo f) = 2*fromEnum (f False) + fromEnum (f True)
toEnum n = Endo (\b->if b then toEnum(n`mod`2) else toEnum (n`div`2))
b2i :: Bool -> Int
b2i = fromEnum
instance Show (Endo Bool) where
show (Endo f) = 'E':concatMap (show.b2i.f) [False,True]
test_roundtrip :: Bool
test_roundtrip = (toEnum :: Int -> Endo Bool) . (fromEnum :: Endo Bool -> Int) == id