packages feed

liquidhaskell-0.8.10.7: tests/ple/pos/RosePLEDiv.hs

{-@ LIQUID "--reflection" @-}
{-@ LIQUID "--ple"        @-}

module Rose1 where 

type Vname = String

{-@ data Pred [psize] @-}

data Pred 
  = Var Vname           -- ^ x, y, z    variables 
  | Not Pred            -- ^ ~ p        negation
  | Or  Pred Pred       -- ^ p1 \/ p2   disjunction
  | And Pred Pred       -- ^ p1 /\ p2   conjunction
  deriving (Show)

{-@ measure psize @-}
{-@ psize :: Pred -> Nat @-}
psize :: Pred -> Int 
psize (Var _)   = 0 
psize (Not p)   = 1 + psize p 
psize (Or p q)  = 1 + mmax (psize p) (psize q) 
psize (And p q) = 1 + mmax (psize p) (psize q) 

{-@ inline mmax @-}
mmax :: Int -> Int -> Int 
mmax x y = if x > y then x else y

{-@ type NNF = {v:Pred | isNNF v} @-}

{-@ measure isNNF @-}
isNNF :: Pred -> Bool 
isNNF (Var _)   = True 
isNNF (And p q) = isNNF p && isNNF q 
isNNF (Or  p q) = isNNF p && isNNF q 
isNNF (Not p)   = isVar p 

{-@ measure isVar @-}
isVar :: Pred -> Bool 
isVar (Var _) = True 
isVar _       = False 

{- MUTUALLY-REC version #1 -}

{-@ reflect nnf @-}
{-@ nnf :: Pred -> NNF @-} 
nnf :: Pred -> Pred 
nnf (Var x)   = Var x
nnf (And p q) = Or (neg p) (neg q)
nnf (Or p q)  = And (neg p) (neg q)
nnf (Not p)   = neg p

{-@ reflect neg @-}
{-@ neg :: Pred -> NNF @-}
neg :: Pred -> Pred
neg (Var x)   = Not (Var x)
neg (And p q) = Or (nnf p) (nnf q)
neg (Or p q)  = And (nnf p) (nnf q)
neg (Not p)   = nnf p


{- SINGLE function version #2 -}

{-@ reflect crunch @-}
{-@ crunch :: Pred -> NNF @-} 
crunch :: Pred -> Pred
crunch (And p q)       = And (crunch p) (crunch q)
crunch (Or p q)	       = Or (crunch p) (crunch q)
crunch (Not (And p q)) = And (crunch (Not p)) (crunch (Not q))
crunch (Not (Or p q))  = Or (crunch (Not p)) (crunch (Not q))
crunch (Not (Not p))   = crunch p
crunch p               = p