liquidhaskell-0.8.10.7: tests/synthesis/static/BSTSort.hs
{-@ LIQUID "--typed-holes" @-}
module BSTSort where
import qualified Data.Set as S
import Language.Haskell.Liquid.Synthesize.Error
{-@ data BST [size] a =
Empty
| Node { x :: a, l :: BST { v: a | v < x }, r :: BST { v: a | x < v } }
@-}
data BST a = Empty | Node a (BST a) (BST a)
{-@ measure size @-}
{-@ size :: BST a -> Nat @-}
size :: BST a -> Int
size Empty = 0
size (Node x l r) = 1 + size l + size r
{-@ measure bstElts @-}
{-@ bstElts :: BST a -> S.Set a @-}
bstElts :: Ord a => BST a -> S.Set a
bstElts Empty = S.empty
bstElts (Node x l r) = S.union (S.singleton x) (S.union (bstElts l) (bstElts r))
{-@ insert :: x: a -> t: BST a -> { v: BST a | bstElts v == S.union (S.singleton x) (bstElts t) } @-}
insert :: Ord a => a -> BST a -> BST a
insert x t =
case t of
Empty -> Node x Empty Empty
Node y l r ->
if x == y
then t
else if y <= x
then Node y l (insert x r)
else Node y (insert x l) r
{-@ toBST :: xs: [a] -> { v: BST a | listElts xs == bstElts v } @-}
toBST :: Ord a => [a] -> BST a
toBST xs =
case xs of
[] -> Empty
x:xs' -> insert x (toBST xs')
{-@ data IList [iLen] a = N | ICons { x0 :: a, xs0 :: IList { v: a | x0 < v } } @-}
data IList a = N | ICons a (IList a)
{-@ measure iLen @-}
{-@ iLen :: IList a -> Nat @-}
iLen :: IList a -> Int
iLen N = 0
iLen (ICons x xs) = 1 + iLen xs
{-@ measure iElts @-}
{-@ iElts :: IList a -> S.Set a @-}
iElts N = S.empty
iElts (ICons x xs) = S.union (S.singleton x) (iElts xs)
{-@ pivotAppend :: p: a -> xs: IList { v: a | v < p } -> ys: IList { v: a | v > p }
-> { v: IList a | iLen v == iLen xs + iLen ys + 1 &&
iElts v == S.union (S.union (iElts xs) (iElts ys)) (S.singleton p) }
@-}
pivotAppend :: a -> IList a -> IList a -> IList a
pivotAppend p xs ys =
case xs of
N -> ICons p ys
ICons x5 x6 -> ICons x5 (pivotAppend p x6 ys)
{-@ flatten :: t: BST a -> { v: IList a | iElts v == bstElts t } @-}
flatten :: BST a -> IList a
flatten t =
case t of
Empty -> N
Node x4 x5 x6 -> pivotAppend x4 (flatten x5) (flatten x6)
{-@ sort' :: xs: [a] -> { v: IList a | iElts v == listElts xs } @-}
sort' :: Ord a => [a] -> IList a
sort' x_S1 = flatten (toBST x_S1)