liquidhaskell-0.8.0.2: tests/todo/baffled.hs
{-@ LIQUID "--no-termination" @-}
{-@ LIQUID "--short-names" @-}
{- LIQUID "--diffcheck" @-}
module AVL where
main :: IO ()
main = return ()
-- Source: https://gist.github.com/gerard/109729
-- | PORTED from: http://docs.camlcity.org/docs/godipkg/4.00/godi-ocaml/lib/ocaml/std-lib/map.ml
data AVL k v = Leaf
| Node { key :: k
, val :: v
, lt :: AVL k v
, rt :: AVL k v
, ht :: Int }
deriving (Show, Eq)
{-@ data AVL k v = Leaf
| Node { key :: k
, val :: v
, lt :: AVLL k v key
, rt :: AVLR k v key
, ht :: AVLH lt rt
}
@-}
{-@ type AVLL k v Key = AVL {k:k | k < Key} v @-}
{-@ type AVLR k v Key = AVL {k:k | Key < k} v @-}
{-@ type AVLH L R = {v:Nat | Ht v L R && Bal L R 2} @-}
{-@ type AVLN k v N = {v:AVL k v | tht v = N} @-}
{-@ predicate LeMax1 V X Y = V <= if X >= Y then 1+X else 1+Y @-}
{-@ predicate EqMax1 V X Y = V = if X >= Y then 1+X else 1+Y @-}
{-@ predicate Diff X Y N = 0 <= X - Y + N && X - Y <= N @-}
{-@ predicate Bal L R N = Diff (tht L) (tht R) N @-}
{-@ predicate Ht V L R = EqMax1 V (tht L) (tht R) @-}
{-@ invariant {v:AVL k v | 0 <= ht v} @-}
{-@ measure tht :: AVL k v -> Int
tht (Leaf) = 0
tht (Node k v l r z) = if (tht l >= tht r) then (1 + tht l) else (1 + tht r)
@-}
{-@ height :: t:_ -> {v:Nat | v = tht t} @-}
height (Leaf) = 0 :: Int
height (Node k v l r z) = if (height l >= height r) then (1 + height l) else (1 + height r)
empty = Leaf
{-@ ht :: t:AVL k v -> {v:Nat | v = tht t} @-}
{-@ create :: key:k -> v -> l:AVLL k v key -> r:{AVLR k v key | Bal l r 2} -> {v:AVL k v | Ht (tht v) l r} @-}
create k v l r = Node k v l r (nodeHeight l r)
{-@ nodeHeight :: l:_ -> r:_ -> {v:Nat | Ht v l r} @-}
nodeHeight l r = h
where
h = if hl >= hr then hl + 1 else hr + 1
hl = height l
hr = height r
{-@ singleton :: k -> v -> AVLN k v 1 @-}
singleton k v = Node k v Leaf Leaf 1
{-@ fox :: k -> v -> thing:AVL k v -> {v: AVL k v | tht thing - 1 <= tht v && tht v <= tht thing + 1} @-}
fox :: k -> v -> AVL k v -> AVL k v
fox key val tree = error "z"
{-@ predicate HtDiff S T D = (tht S) - (tht T) == D @-}
{-@ add :: k -> v -> t:AVL k v -> {v: AVL k v | (tht t - 1 <= tht v || tht t - 2 = tht v) && tht v <= tht t + 1} @-}
add k' v' t@(Node k v l r h)
-- RJ: This case is obviously fine
| k' == k = Node k' v' l r h
-- RJ: Maddeningly, this case is fine too
-- | k' < k = let mickey = fox k' v' l
-- in
-- bal k v mickey r
-- NV: This is fine
-- | k < k', height l >= height r = let mouse = fox k' v' r in
-- bal k v l mouse
-- RJ: HEREHEREHERE this is the problem (I GIVE UP)
-- here it might be the case that 'tht t - 2 = tht v'
| k < k', height l < height r = let mouse = fox k' v' r in
bal k v l mouse
add k' v' Leaf = singleton k' v'
{-@ bal :: key:k -> v -> l:AVLL k v key -> r:{AVLR k v key | Bal l r 3} -> {v:AVL k v | tht l <= tht v && tht r <= tht v && (tht l >= tht r => tht v <= 1 + tht l) && (tht r >= tht l => tht v <= 1 + tht r) } @-}
bal :: k -> v -> AVL k v -> AVL k v -> AVL k v
bal k v l r
| hl > hr + 2 = balL k v l r
| hr > hl + 2 = balR k v l r
| otherwise = create k v l r
where
hl = height l
hr = height r
{-@ balL :: k:_ -> v:_ -> l:AVLL k v k -> r:AVLN {v:_ | k < v} v {(tht l) - 3} -> {v:AVL k v | tht l <= tht v && tht v <= 1 + tht l} @-}
balL k v l@(Node lk lv ll lr _) r
| height ll >= height lr = let tmp = create k v lr r in lAssert (height tmp <= height l) $ create lk lv ll tmp
| otherwise = case lr of
Node lrk lrv lrl lrr _ -> create lrk lrv (create lk lv ll lrl) (create k v lrr r)
Leaf -> die "all done"
-- balL k v (Node lk lv ll lr@(Node lrk lrv lrl lrr _) _) r
-- | height ll < height lr = create lrk lrv (create lk lv ll lrl) (create k v lrr r)
{-@ balR :: k:_ -> v:_ -> l:AVLL k v k -> r:AVLN {v:_ | k < v} v {(tht l) + 3} -> {v: AVL k v | tht r <= tht v && tht v <= 1 + tht r} @-}
balR k v l r@(Node rk rv rl rr _)
| height rr >= height rl = create rk rv (create k v l rl) rr
| otherwise = case rl of
Node rlk rlv rll rlr _ -> create rlk rlv (create k v l rll) (create rk rv rlr rr)
Leaf -> die "all done"
-- balR k v l r@(Node rk rv rl@(Node rlk rlv rll rlr _) rr _)
-- | height rr < height rl = create rlk rlv (create k v l rll) (create rk rv rlr rr)
{-@ die :: {v:String | false } -> a @-}
die x = error x
{-@ lAssert :: {v:Bool | Prop v} -> a -> a @-}
lAssert True x = x
lAssert _ z = z