|
Packit |
1d8052 |
{-# LANGUAGE ScopedTypeVariables, TemplateHaskell #-}
|
|
Packit |
1d8052 |
module Main where
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
--------------------------------------------------------------------------
|
|
Packit |
1d8052 |
-- imports
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
import Test.QuickCheck
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
import Text.Show.Functions
|
|
Packit |
1d8052 |
import Data.List
|
|
Packit |
1d8052 |
( sort
|
|
Packit |
1d8052 |
, group
|
|
Packit |
1d8052 |
, nub
|
|
Packit |
1d8052 |
, (\\)
|
|
Packit |
1d8052 |
)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
import Control.Monad
|
|
Packit |
1d8052 |
( liftM
|
|
Packit |
1d8052 |
, liftM2
|
|
Packit |
1d8052 |
)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
import Data.Maybe
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
--import Text.Show.Functions
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
--------------------------------------------------------------------------
|
|
Packit |
1d8052 |
-- binary search trees
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
data Set a
|
|
Packit |
1d8052 |
= Node a (Set a) (Set a)
|
|
Packit |
1d8052 |
| Empty
|
|
Packit |
1d8052 |
deriving ( Eq, Ord, Show )
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
empty :: Set a
|
|
Packit |
1d8052 |
empty = Empty
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
isEmpty :: Set a -> Bool
|
|
Packit |
1d8052 |
isEmpty Empty = True
|
|
Packit |
1d8052 |
isEmpty _ = False
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
unit :: a -> Set a
|
|
Packit |
1d8052 |
unit x = Node x empty empty
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
size :: Set a -> Int
|
|
Packit |
1d8052 |
size Empty = 0
|
|
Packit |
1d8052 |
size (Node _ s1 s2) = 1 + size s1 + size s2
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
insert :: Ord a => a -> Set a -> Set a
|
|
Packit |
1d8052 |
insert x s = s `union` unit x
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
merge :: Set a -> Set a -> Set a
|
|
Packit |
1d8052 |
s `merge` Empty = s
|
|
Packit |
1d8052 |
s `merge` Node x Empty s2 = Node x s s2
|
|
Packit |
1d8052 |
s `merge` Node x (Node y s11 s12) s2 = Node y s (Node x (s11 `merge` s12) s2)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
delete :: Ord a => a -> Set a -> Set a
|
|
Packit |
1d8052 |
delete x Empty = Empty
|
|
Packit |
1d8052 |
delete x (Node x' s1 s2) =
|
|
Packit |
1d8052 |
case x `compare` x' of
|
|
Packit |
1d8052 |
LT -> Node x' (delete x s1) s2
|
|
Packit |
1d8052 |
EQ -> s1 `merge` s2
|
|
Packit |
1d8052 |
GT -> Node x' s1 (delete x s2)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
union :: Ord a => Set a -> Set a -> Set a
|
|
Packit |
1d8052 |
{-
|
|
Packit |
1d8052 |
s1 `union` Empty = s1
|
|
Packit |
1d8052 |
Empty `union` s2 = s2
|
|
Packit |
1d8052 |
s1@(Node x s11 s12) `union` s2@(Node y s21 s22) =
|
|
Packit |
1d8052 |
case x `compare` y of
|
|
Packit |
1d8052 |
LT -> Node x s11 (s12 `union` Node y Empty s22) `union` s21
|
|
Packit |
1d8052 |
EQ -> Node x (s11 `union` s21) (s12 `union` s22)
|
|
Packit |
1d8052 |
--GT -> s11 `union` Node y s21 (Node x Empty s12 `union` s22)
|
|
Packit |
1d8052 |
GT -> Node x (s11 `union` Node y s21 Empty) s12 `union` s22
|
|
Packit |
1d8052 |
-}
|
|
Packit |
1d8052 |
s1 `union` Empty = s1
|
|
Packit |
1d8052 |
Empty `union` s2 = s2
|
|
Packit |
1d8052 |
Node x s11 s12 `union` s2 = Node x (s11 `union` s21) (s12 `union` s22)
|
|
Packit |
1d8052 |
where
|
|
Packit |
1d8052 |
(s21,s22) = split x s2
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
split :: Ord a => a -> Set a -> (Set a, Set a)
|
|
Packit |
1d8052 |
split x Empty = (Empty, Empty)
|
|
Packit |
1d8052 |
split x (Node y s1 s2) =
|
|
Packit |
1d8052 |
case x `compare` y of
|
|
Packit |
1d8052 |
LT -> (s11, Node y s12 s2)
|
|
Packit |
1d8052 |
EQ -> (s1, s2)
|
|
Packit |
1d8052 |
GT -> (Node y s1 s21, s22)
|
|
Packit |
1d8052 |
where
|
|
Packit |
1d8052 |
(s11,s12) = split x s1
|
|
Packit |
1d8052 |
(s21,s22) = split x s2
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
mapp :: (a -> b) -> Set a -> Set b
|
|
Packit |
1d8052 |
mapp f Empty = Empty
|
|
Packit |
1d8052 |
mapp f (Node x s1 s2) = Node (f x) (mapp f s1) (mapp f s2)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
fromList :: Ord a => [a] -> Set a
|
|
Packit |
1d8052 |
--fromList xs = build [ (empty,x) | x <- sort xs ]
|
|
Packit |
1d8052 |
fromList xs = build [ (empty,head x) | x <- group (sort xs) ]
|
|
Packit |
1d8052 |
where
|
|
Packit |
1d8052 |
build [] = empty
|
|
Packit |
1d8052 |
build [(s,x)] = attach x s
|
|
Packit |
1d8052 |
build sxs = build (sweep sxs)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
sweep [] = []
|
|
Packit |
1d8052 |
sweep [sx] = [sx]
|
|
Packit |
1d8052 |
sweep ((s1,x1):(s2,x2):sxs) = (Node x1 s1 s2,x2) : sweep sxs
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
attach x Empty = unit x
|
|
Packit |
1d8052 |
attach x (Node y s1 s2) = Node y s1 (attach x s2)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
toList :: Set a -> [a]
|
|
Packit |
1d8052 |
toList s = toSortedList s
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
toSortedList :: Set a -> [a]
|
|
Packit |
1d8052 |
toSortedList s = toList' s []
|
|
Packit |
1d8052 |
where
|
|
Packit |
1d8052 |
toList' Empty xs = xs
|
|
Packit |
1d8052 |
toList' (Node x s1 s2) xs = toList' s1 (x : toList' s2 xs)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
--------------------------------------------------------------------------
|
|
Packit |
1d8052 |
-- generators
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
instance (Ord a, Arbitrary a) => Arbitrary (Set a) where
|
|
Packit |
1d8052 |
arbitrary = sized (arbSet Nothing Nothing)
|
|
Packit |
1d8052 |
where
|
|
Packit |
1d8052 |
arbSet mx my n =
|
|
Packit |
1d8052 |
frequency $
|
|
Packit |
1d8052 |
[ (1, return Empty) ] ++
|
|
Packit |
1d8052 |
[ (7, do mz <- arbitrary `suchThatMaybe` (isOK mx my)
|
|
Packit |
1d8052 |
case mz of
|
|
Packit |
1d8052 |
Nothing -> return Empty
|
|
Packit |
1d8052 |
Just z -> liftM2 (Node z) (arbSet mx mz n2)
|
|
Packit |
1d8052 |
(arbSet mz my n2)
|
|
Packit |
1d8052 |
where n2 = n `div` 2)
|
|
Packit |
1d8052 |
| n > 0
|
|
Packit |
1d8052 |
]
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
isOK mx my z =
|
|
Packit |
1d8052 |
maybe True (
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
shrink Empty = []
|
|
Packit |
1d8052 |
shrink t@(Node x s1 s2) = [ s1, s2 ]
|
|
Packit |
1d8052 |
++ [ t' | x' <- shrink x, let t' = Node x' s1 s2, invariant t' ]
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
-- instance (Ord a, ShrinkSub a) => ShrinkSub (Set a)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
--------------------------------------------------------------------------
|
|
Packit |
1d8052 |
-- properties
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
(.<) :: Ord a => Set a -> a -> Bool
|
|
Packit |
1d8052 |
Empty .< x = True
|
|
Packit |
1d8052 |
Node y _ s .< x = y < x && s .< x
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
(<.) :: Ord a => a -> Set a -> Bool
|
|
Packit |
1d8052 |
x <. Empty = True
|
|
Packit |
1d8052 |
x <. Node y _ s = x < y && x <. s
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
(==?) :: Ord a => Set a -> [a] -> Bool
|
|
Packit |
1d8052 |
s ==? xs = invariant s && sort (toList s) == nub (sort xs)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
invariant :: Ord a => Set a -> Bool
|
|
Packit |
1d8052 |
invariant Empty = True
|
|
Packit |
1d8052 |
invariant (Node x s1 s2) = s1 .< x && x <. s2 && invariant s1 && invariant s2
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Invariant (s :: Set Int) =
|
|
Packit |
1d8052 |
invariant s
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Empty =
|
|
Packit |
1d8052 |
empty ==? ([] :: [Int])
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Unit (x :: Int) =
|
|
Packit |
1d8052 |
unit x ==? [x]
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Size (s :: Set Int) =
|
|
Packit |
1d8052 |
cover (size s >= 15) 60 "large" $
|
|
Packit |
1d8052 |
size s == length (toList s)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Insert x (s :: Set Int) =
|
|
Packit |
1d8052 |
insert x s ==? (x : toList s)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Delete x (s :: Set Int) =
|
|
Packit |
1d8052 |
delete x s ==? (toList s \\ [x])
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Union s1 (s2 :: Set Int) =
|
|
Packit |
1d8052 |
(s1 `union` s2) ==? (toList s1 ++ toList s2)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_Mapp (f :: Int -> Int) (s :: Set Int) =
|
|
Packit |
1d8052 |
expectFailure $
|
|
Packit |
1d8052 |
whenFail (putStrLn ("Fun: " ++ show [ (x,f x) | x <- toList s])) $
|
|
Packit |
1d8052 |
mapp f s ==? map f (toList s)
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_FromList (xs :: [Int]) =
|
|
Packit |
1d8052 |
fromList xs ==? xs
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_ToSortedList (s :: Set Int) =
|
|
Packit |
1d8052 |
s ==? xs && xs == sort xs
|
|
Packit |
1d8052 |
where
|
|
Packit |
1d8052 |
xs = toSortedList s
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
-- whenFail (putStrLn ("Result: " ++ show (fromList xs))) $
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
prop_FromList' (xs :: [Int]) =
|
|
Packit |
1d8052 |
shrinking shrink xs $ \xs' ->
|
|
Packit |
1d8052 |
fromList xs ==? xs
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
--------------------------------------------------------------------------
|
|
Packit |
1d8052 |
-- main
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
return []
|
|
Packit |
1d8052 |
main = $quickCheckAll
|
|
Packit |
1d8052 |
|
|
Packit |
1d8052 |
--------------------------------------------------------------------------
|
|
Packit |
1d8052 |
-- the end.
|