packages feed

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

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

module T1371_NNF where

import Prelude hiding (lookup)

data Pred
  = Var Int
  | Not Pred
  | Or  Pred Pred
  | And Pred Pred

{-@ reflect lookup @-}
lookup :: [a] -> a -> Int -> a
lookup []     def _ = def
lookup (v:vs) def k
  | k == 0          = v
  | k <  0          = def
  | otherwise       = lookup vs def (k-1)

{-@ reflect eval @-}
eval :: [Bool] -> Pred -> Bool
eval s (Var i)   = lookup s False i
eval s (And f g) = (eval s f) && (eval s g)
eval s (Or  f g) = (eval s f) || (eval s g)
eval s (Not f)   = not (eval s f)

{-@ reflect nnf @-}
nnf :: Pred -> Pred
nnf (Var i)    = (Var i)
nnf (And p q)  = And (nnf p) (nnf q)
nnf (Or  p q)  = Or  (nnf p) (nnf q)
nnf (Not f)    = nnf' f

{-@ reflect nnf' @-}
nnf' :: Pred -> Pred
nnf' (Not g)   = nnf g
nnf' (Var i)   = Not (Var i)
-- nnf' (Or  p q) = And (nnf' p) (nnf' q)                -- OK
-- nnf' (And p q) = Or  (nnf' p) (nnf' q)                -- OK
nnf' (Or  p q) = And (nnf (Not p)) (nnf (Not q))   -- PLE-DIVERGES
nnf' (And p q) = Or  (nnf (Not p)) (nnf (Not q))   -- PLE-DIVERGES

-- ODDLY, you need BOTH the PLE-DIVERGES cases to tickle the divergence...

{-@ thm :: s:[Bool] -> p:Pred -> { eval s p = eval s (nnf p) } @-}
thm :: [Bool] -> Pred -> Bool
thm s (Var i)         = True
-- thm s (And p q)       = thm s p && thm s q
-- thm s (Or  p q)       = thm s p && thm s q
-- thm s (Not p)         = undefined
thm _ _ = undefined