liquidhaskell-0.8.10.7: benchmarks/popl18/ple/pos/NaturalDeduction.hs
-- Author Niki Vazou
-- Natural Deduction Rules for Quantifiers
-- Proofs from http://hume.ucdavis.edu/mattey/phi112/112dedurles_ho.pdf
-- and file:///Users/niki/Downloads/Gentzen%201935%20-%20Investigations%20into%20Logical%20Deduction%20(1).pdf
module Examples where
{-@ LIQUID "--higherorder" @-}
import Language.Haskell.Liquid.ProofCombinators
-- Universal Introduction
{-@
ex1 :: f:(a -> Bool) -> g:(a -> Bool)
-> (x:a -> PAnd {v:Proof | f x} {v:Proof | g x})
-> (y:a -> {v:Proof | f y})
@-}
ex1 :: (a -> Bool) -> (a -> Bool)
-> (a -> PAnd Proof Proof)
-> (a -> Proof)
ex1 f g assumption y =
case assumption y of
PAnd fy _ -> fy
class NonEmpty a where
pick :: a
-- Existential Introduction
{-@ ex2 :: f:(a -> Bool) -> (x:a -> {v:Proof | f x})
-> (y::a,{v:Proof | f y}) @-}
ex2 :: NonEmpty a => (a -> Bool) -> (a -> Proof) -> (a,Proof)
ex2 f fx = (y, fx y)
where
y = pick
-- Existential Elimination
-- exists x. (f x && g x)
-- =>
-- exists x. f x && exists x. g x
{-@ existsAllDistr :: f:(a -> Bool) -> g:(a -> Bool) -> (x::a, PAnd {v:Proof | f x} {v:Proof | g x})
-> PAnd (x::a, {v:Proof | f x}) (x::a, {v:Proof | g x}) @-}
existsAllDistr :: (a -> Bool) -> (a -> Bool) -> (a,PAnd Proof Proof) -> PAnd (a,Proof) (a,Proof)
existsAllDistr f g (x,PAnd fx gx) = PAnd (x,fx) (x,gx)
-- exists x. (f x || g x)
-- =>
-- (exists x. f x) || (exists x. g x)
{-@ existsOrDistr :: f:(a -> Bool) -> g:(a -> Bool) -> (x::a, POr {v:Proof | f x} {v:Proof | g x})
-> POr (x::a, {v:Proof | f x}) (x::a, {v:Proof | g x}) @-}
existsOrDistr :: (a -> Bool) -> (a -> Bool) -> (a,POr Proof Proof) -> POr (a,Proof) (a,Proof)
existsOrDistr f g (x,POrLeft fx) = POrLeft (x,fx)
existsOrDistr f g (x,POrRight fx) = POrRight (x,fx)
-- forall x. (f x && g x)
-- =>
-- (forall x. f x && forall x g x)
{-@ forallAndDistr :: f:(a -> Bool) -> g:(a -> Bool) -> (x:a -> PAnd {v:Proof | f x} {v:Proof | g x})
-> PAnd (x:a -> {v:Proof | f x}) (x:a -> {v:Proof | g x}) @-}
forallAndDistr :: (a -> Bool) -> (a -> Bool) -> (a -> PAnd Proof Proof) -> PAnd (a -> Proof) (a -> Proof)
forallAndDistr f g andx
= PAnd (\x -> case andx x of PAnd fx _ -> fx)
(\x -> case andx x of PAnd _ gx -> gx)
-- forall x. (exists y. (p x => q x y))
-- =>
-- forall x. (p x => exists y. q x y)
{-@ forallExistsImpl :: p:(a -> Bool) -> q:(a -> a -> Bool)
-> (x:a -> (y::a, {v:Proof | p x} -> {v:Proof | q x y} ))
-> (x:a -> ({v:Proof | p x} -> (y::a, {v:Proof | q x y})))@-}
forallExistsImpl :: (a -> Bool) -> (a -> a -> Bool)
-> (a -> (a,Proof -> Proof))
-> (a -> (Proof -> (a,Proof)))
forallExistsImpl p q f x px
= case f x of
(y, pxToqxy) -> (y,pxToqxy px)
-- Gentze examples
gentze1 :: Bool -> Bool -> Bool -> Proof
{-@ gentze1 :: x:Bool -> y:Bool -> z:Bool -> { (x || (y && z)) => ((x || y) && (x || z)) } @-}
gentze1 _ _ _ = ()
gentze2 :: (a -> a -> Bool) -> (a,a -> Proof) -> a -> (a,Proof)
{-@ gentze2 :: f:(a -> a -> Bool) -> (x::a,y:a -> {v:Proof | f x y}) -> y:a -> (x::a,{v:Proof | f x y}) @-}
gentze2 f (x,fxy) y = (x,fxy y)
gentze3 :: (a -> Bool) -> ((a, Proof)-> Proof) -> a -> Proof -> Proof
{-@ gentze3 :: f:(a -> Bool) -> ((x::a, {v:Proof | f x})-> {v:Proof | false})
-> y:a -> {v:Proof | f y} -> {v:Proof | false} @-}
gentze3 f notexistsfx y fy =
notexistsfx (y, fy)
data POr a b = POrLeft a | POrRight b
data PAnd a b = PAnd a b