import Test.FitSpec import Data.List type Add a = a -> a -> a type Prod a = a -> a -> a type Ty a = ( Add a , Prod a ) properties :: (Listable a, Show a, Eq a, Num a) => Add a -> Prod a -> [Property] properties (+) (*) = [ property $ \x y -> x + y == y + x , property $ \x y z -> x + (y + z) == (x + y) + z , property $ \x -> x + 0 == x , property $ \x -> 0 + x == x , property $ \x y -> x * y == y * x , property $ \x y z -> x * (y * z) == (x * y) * z , property $ \x -> x * 1 == x , property $ \x -> 1 * x == x , property $ \x y z -> x * (y + z) == (x * y) + (x * z) , property $ \x y z -> (y + z) * x == (y * x) + (z * x) ] fns :: Integral a => Ty a fns = ((+),(*)) sargs :: Args sargs = args { timeout = 0 , nMutants = 1000 , nTests = 1000 , names = [ "x + y", "x * y" ] } -- , extraMutants = -- let ems = [ \x y -> x+y+1 -- , \x y -> x*y+x*y -- , \x y -> x+y+x+y -- , (+++) -- , min -- , max -- -- another good example would be -- -- || and && defined over integers -- ] -- in drop 1 [ (s,p) -- | False -- was useExtra -- , s <- (+):(*):ems -- , p <- (*):(+):ems -- ] main :: IO () main = do as <- getArgsWith sargs let run f = reportWith as f (uncurry properties) case concat (extra as) of "int" -> run (fns :: Ty Int) "int2" -> run (fns :: Ty UInt2) "int3" -> run (fns :: Ty UInt3) "" -> run (fns :: Ty UInt2) (+++) :: (Show a, Read a, Integral a) => a -> a -> a x +++ 0 = x 0 +++ y = y x +++ y = read (show x ++ show (abs y))