-
Notifications
You must be signed in to change notification settings - Fork 0
/
heaps.hs
108 lines (90 loc) · 3.71 KB
/
heaps.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
105
106
107
108
{-# 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