liquidhaskell-0.8.10.7: tests/ple/pos/tmp.hs
{-@ LIQUID "--reflection" @-}
{-@ LIQUID "--ple" @-}
{-@ LIQUID "--no-termination" @-}
module Tutorial6 where
import Prelude hiding (lookup)
data Wff = Var Int
| Not Wff
| Wff :|: Wff
| Wff :&: Wff
deriving (Eq, Ord)
data NNF = Atom Bool Int
| NOr NNF NNF
| NAnd NNF NNF
{-@ reflect toWff @-}
toWff :: NNF -> Wff
toWff (Atom True i) = Var i
toWff (Atom False i) = Not (Var i)
toWff (NOr f g) = toWff f :|: toWff g
toWff (NAnd f g) = toWff f :&: toWff g
{-@ reflect lookup @-}
lookup :: [a] -> a -> Int -> a
lookup [] def _ = def
lookup (v:_) _ 0 = v
lookup (_:vs) def k = lookup vs def (k-1)
{-@ reflect eval @-}
eval :: [Bool] -> Wff -> Bool
eval s (Var i) = lookup s False i
eval s (f :&: g) = eval s f && eval s g
eval s (f :|: g) = (eval s f) || (eval s g)
eval s (Not f) = not (eval s f)
{-@ reflect evalNNF @-}
evalNNF :: [Bool] -> NNF -> Bool
evalNNF s (Atom True i) = lookup s False i
evalNNF s (Atom False i) = not (lookup s False i)
evalNNF s (NOr p q) = evalNNF s p || evalNNF s q
evalNNF s (NAnd p q) = evalNNF s p && evalNNF s q
{-@ toNNF :: s:[Bool] -> p:Wff -> { q: NNF | eval s p = evalNNF s q } @-}
toNNF :: [Bool] -> Wff -> NNF
toNNF _ (Var i) = Atom True i
toNNF s (Not p) = case p of
Not p -> let glub = toNNF s p in glub
_ -> undefined
toNNF _ _ = undefined