-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmergeheaps.hs
104 lines (88 loc) · 3.12 KB
/
mergeheaps.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
{-# 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
instance (Ord a, Listable a) => Mutable (Heap a) where
mutiers = mutiersEq
instance (Ord a, Show a, Listable a) => ShowMutable (Heap a) where
mutantS = mutantSEq
type Merge a = Heap a -> Heap a -> Heap a
type Ty a = Merge a
properties :: (Ord a, Show a, Listable a)
=> Merge a
-> [Property]
properties merge =
[ property $ \h h1 -> merge h h1 == merge h1 h
, property $ \h -> merge h Nil == h
, property $ \x h h1 -> merge h (insert x h1) == insert x (merge h h1)
, property $ \h h1 h2 -> merge h (merge h1 h2) == merge h1 (merge h h2)
, property $ \h -> notNull h ==> findMin (merge h h) == findMin h
, property $ \h -> null (merge h h) == null h
, property $ \h -> notNull h ==> merge h (deleteMin h) == deleteMin (merge h h)
, property $ \h h1 -> (null h && null h1) == null (merge h h1)
--, property $ \xs ys -> merge (fromList xs) (fromList ys) == fromList (xs++ys)
--, property $ \h h1 -> mergeLists (toList h) (toList h1) == toList (merge h h1)
]
where notNull = not . null
sargs = args
{ timeout = 0
, nMutants = 500
, nTests = 500
, names = ["merge h h'"]
}
em :: (Bounded a, Ord a) => [Ty a]
em = take 4
[ (\_ _ -> Nil)
, maxMerge
, crazyMerge
, mergeEqNil
]
main :: IO ()
main = do
as <- getArgsWith sargs
let run f = reportWithExtra em as f properties
case concat (extra as) of
"bool" -> run (merge :: Ty Bool)
"bools" -> run (merge :: Ty [Bool])
"i" -> run (merge :: Ty Int)
"i1" -> run (merge :: Ty Int1)
"i2" -> run (merge :: Ty Int2)
"i3" -> run (merge :: Ty Int3)
"w1" -> run (merge :: Ty Word1)
"w2" -> run (merge :: Ty Word2)
"w3" -> run (merge :: Ty Word3)
"unit" -> run (merge :: Ty ())
"" -> run (merge :: 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
mergeEqNil :: (Ord a) => Heap a -> Heap a -> Heap a
mergeEqNil h h1 | h == h1 = Nil
| otherwise = merge h h1
-- Only necessary for crazyMerge + bools to compile
-- (it won't run, because it won't be able to PRINT surviving
-- mutants).
-- all other types should work fine
instance Bounded a => Bounded [a] where
minBound = []
maxBound = repeat maxBound