-- tree.hs: conjuring functions over trees -- -- Copyright (C) 2021 Rudy Matela -- Distributed under the 3-Clause BSD licence (see the file LICENSE). {-# LANGUAGE CPP, TemplateHaskell #-} #if __GLASGOW_HASKELL__ == 708 {-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-} import Data.Typeable (Typeable) #endif import Conjure import Test.LeanCheck import Data.Express hiding (height,size) -- TODO: remove the following import -- and fix build on GHC 7.10 and 7.8 -- the generation of -: and ->>>: somehow fails. import Test.LeanCheck.Utils data Tree = Leaf | Node Tree Int Tree deriving (Eq, Ord, Show, Read) #if __GLASGOW_HASKELL__ == 708 deriving instance Typeable Tree #endif deriveExpress ''Tree unit :: Int -> Tree unit x = Node Leaf x Leaf nil :: Tree -> Bool nil Leaf = True nil _ = False left :: Tree -> Tree left (Node l _ _) = l right :: Tree -> Tree right (Node _ _ r) = r valu :: Tree -> Int valu (Node _ x _) = x leftmost :: Tree -> Int leftmost (Node l x _) = if nil l then x else leftmost l rightmost :: Tree -> Int rightmost (Node _ x r) = if nil r then x else rightmost r height :: Tree -> Int height Leaf = -1 height (Node l _ r) = 1 + max (height l) (height r) size :: Tree -> Int size Leaf = 0 size (Node l _ r) = size l + 1 + size r ordered :: Tree -> Bool ordered Leaf = True ordered (Node l x r) = (nil l || rightmost l < x) && (nil r || x < leftmost r) && ordered l && ordered r preorder :: Tree -> [Int] preorder Leaf = [] preorder (Node l x r) = [x] ++ preorder l ++ preorder r inorder :: Tree -> [Int] inorder Leaf = [] inorder (Node l x r) = inorder l ++ [x] ++ inorder r posorder :: Tree -> [Int] posorder Leaf = [] posorder (Node l x r) = posorder l ++ posorder r ++ [x] -- this mem searches both sides of the tree mem :: Int -> Tree -> Bool mem _ Leaf = False mem y (Node l x r) = y == x || mem y l || mem y r instance Listable Tree where tiers = cons0 Leaf \/ cons3 Node instance Name Tree where name _ = "t1" instance Conjurable Tree where conjureExpress = reifyExpress conjureEquality = reifyEquality conjureTiers = reifyTiers conjureSubTypes x = conjureType (undefined :: Int) conjureSize = size conjureCases t = [ val (Leaf -: t) , value "Node" (Node ->>>: t) :$ hole l :$ hole x :$ hole r ] where Node l x r = Node undefined undefined undefined -: t main :: IO () main = do conjure "leftmost" leftmost [ prim "undefined" (undefined :: Int) , prif (undefined :: Int) , prim "nil" nil ] conjure "rightmost" rightmost [ prim "undefined" (undefined :: Int) , prif (undefined :: Int) , prim "nil" nil ] conjure "size" size [ pr (0 :: Int) , pr (1 :: Int) , prim "+" ((+) :: Int -> Int -> Int) , prim "nil" nil ] conjure "height" height [ pr (0 :: Int) , pr (1 :: Int) , pr (-1 :: Int) , prim "+" ((+) :: Int -> Int -> Int) , prim "max" (max :: Int -> Int -> Int) , prim "nil" nil ] conjure "mem" mem [ pr False , prim "||" (||) , prim "==" ((==) :: Int -> Int -> Bool) ] -- unreachable: needs size 22 but OOMs at 18 conjureWithMaxSize 12 "ordered" ordered [ pr True , pr False , prim "&&" (&&) , prim "||" (||) , prim "<" ((<) :: Int -> Int -> Bool) , prim "rightmost" rightmost , prim "leftmost" leftmost ] conjure "ordered" ordered [ prim "strictlyOrdered" (strictlyOrdered :: [Int] -> Bool) , prim "inorder" inorder ] conjureWithMaxSize 12 "preorder" preorder [ pr ([] :: [Int]) , prim ":" ((:) :: Int -> [Int] -> [Int]) , prim "++" ((++) :: [Int] -> [Int] -> [Int]) ] conjureWithMaxSize 12 "inorder" inorder [ pr ([] :: [Int]) , prim ":" ((:) :: Int -> [Int] -> [Int]) , prim "++" ((++) :: [Int] -> [Int] -> [Int]) ] conjureWithMaxSize 12 "posorder" posorder [ pr ([] :: [Int]) , prim ":" ((:) :: Int -> [Int] -> [Int]) , prim "++" ((++) :: [Int] -> [Int] -> [Int]) ] strictlyOrdered :: [Int] -> Bool strictlyOrdered [] = True strictlyOrdered (x:xs) = (null xs || x < head xs) && strictlyOrdered xs