fitspec-0.4.4: bench/heaps.hs
{-# Language DeriveDataTypeable, NoMonomorphismRestriction #-}
import Test.FitSpec
import Prelude hiding (null)
import qualified Data.List as L
import Data.Maybe (listToMaybe)
import Heap
import Control.Monad (unless)
instance (Ord a, Listable a) => Listable (Heap a) where
tiers = bagCons fromList
-- a good property to assure that the above does not leave out elements is:
--
-- \xs ys = xs `permutation` ys <==> fromList xs == fromList ys
-- `asTypeOf` (undefined :: Heap a)
instance (Ord a, Listable a) => Mutable (Heap a) where
mutiers = mutiersEq
instance (Ord a, Show a, Listable a) => ShowMutable (Heap a) where
mutantS = mutantSEq
-- Alias for type (they are repeated a lot)
type Insert a = a -> Heap a -> Heap a
type DeleteMin a = Heap a -> Heap a
type Merge a = Heap a -> Heap a -> Heap a
type Ty a = (Insert a, DeleteMin a, Merge a)
properties :: (Ord a, Show a, Listable a)
=> Insert a
-> DeleteMin a
-> Merge a
-> [Property]
properties insert' deleteMin' merge' =
[ property $ \x y h -> insert' x (insert' y h) == insert' y (insert' x h) -- 1
, property $ \h x -> null (insert' x h) == False -- 2
, property $ \x h -> L.insert x (toList h) == toList (insert' x h) -- 3
, property $ \h h1 -> merge' h h1 == merge' h1 h -- 4
, property $ \h -> merge' h Nil == h -- 5
, property $ \h h1 h2 -> merge' h (merge' h1 h2) == merge' h1 (merge' h h2) -- 6
, property $ \h -> not (null h) ==> findMin (merge' h h) == findMin h -- 7
, property $ \h -> null (merge' h h) == null h -- 8
, property $ \h h1 -> (null h && null h1) == null (merge' h h1) -- 9
, property $ \h h1 x -> merge' h (insert' x h1) == insert' x (merge' h h1) -- 10
, property $ \h -> not (null h) ==> merge' h (deleteMin' h) == deleteMin' (merge' h h) -- 11
, property $ \x -> deleteMin' (insert' x Nil) == Nil -- 12
]
sargs = args
{ timeout = 0
, nMutants = 500
, nTests = 500
, names = ["insert x h","deleteMin h","merge h h'"]
--, extraMutants = take 0 [(uncurry maxInsert,maxDeleteMin,uncurry maxMerge)] }
}
fns :: Ord a => Ty a
fns = (insert, deleteMin, merge)
em :: (Bounded a, Ord a) => [Ty a]
em = take 3
[ (maxInsert, maxDeleteMin, maxMerge)
, (insert, deleteMin, crazyMerge)
, (\i h -> Nil, deleteMin, merge)
]
main :: IO ()
main = do
as <- getArgsWith sargs
let run f = reportWithExtra em as f (uncurry3 properties)
case concat (extra as) of
-- "bool" -> run (fns :: Ty Bool)
-- "bools" -> run (fns :: Ty [Bool])
"i" -> run (fns :: Ty Int)
"i1" -> run (fns :: Ty Int1)
"i2" -> run (fns :: Ty Int2)
"i3" -> run (fns :: Ty Int3)
"w1" -> run (fns :: Ty Word1)
"w2" -> run (fns :: Ty Word2)
"w3" -> run (fns :: Ty Word3)
"unit" -> run (fns :: Ty ())
"" -> run (fns :: Ty Word2)
maxInsert :: Ord a => a -> Heap a -> Heap a
maxInsert x h = maxMerge h (branch x Nil Nil)
maxDeleteMin :: Ord a => Heap a -> Heap a
maxDeleteMin (Branch _ _ l r) = maxMerge l r
maxDeleteMin Nil = Nil
maxMerge :: Ord a => Heap a -> Heap a -> Heap a
maxMerge Nil h = h
maxMerge h Nil = h
maxMerge h1@(Branch _ x1 l1 r1) h2@(Branch _ x2 l2 r2)
| x1 >= x2 = branch x1 (maxMerge l1 h2) r1
| otherwise = maxMerge h2 h1
uncurry3 :: (a->b->c->d) -> (a,b,c) -> d
uncurry3 f (x,y,z) = f x y z
crazyMerge :: (Bounded a, Ord a) => Heap a -> Heap a -> Heap a
crazyMerge Nil Nil = Nil
crazyMerge Nil h = h
crazyMerge h Nil = h
crazyMerge h h1 = insert maxBound $ merge h h1