{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Algebra.Heyting.Free.Expr (
Expr (..),
proofSearch,
) where
import Prelude ()
import Prelude.Compat
import Control.Monad (ap)
import Control.Monad.Trans.State (State, evalState, get, put)
import Data.Data (Data, Typeable)
import Data.Set (Set)
import GHC.Generics (Generic, Generic1)
import qualified Data.Set as Set
data Expr a
= Var a
| Bottom
| Top
| Expr a :/\: Expr a
| Expr a :\/: Expr a
| Expr a :=>: Expr a
deriving (Eq, Ord, Show, Functor, Foldable, Traversable, Generic, Generic1, Data, Typeable)
infixr 6 :/\:
infixr 5 :\/:
infixr 4 :=>:
instance Applicative Expr where
pure = Var
(<*>) = ap
instance Monad Expr where
return = pure
Var x >>= k = k x
Bottom >>= _ = Bottom
Top >>= _ = Top
(x :/\: y) >>= k = (x >>= k) :/\: (y >>= k)
(x :\/: y) >>= k = (x >>= k) :\/: (y >>= k)
(x :=>: y) >>= k = (x >>= k) :=>: (y >>= k)
proofSearch :: forall a. Ord a => Expr a -> Bool
proofSearch tyGoal = evalState (emptyCtx |- fmap R tyGoal) 0
where
freshVar = do
n <- get
put (n + 1)
return (L n)
infix 4 |-
infixr 3 .&&
(.&&) :: Monad m => m Bool -> m Bool -> m Bool
x .&& y = do
x' <- x
if x'
then y
else return False
(|-) :: Ctx a -> Expr (Am a) -> State Int Bool
_ctx |- Top
= return True
Ctx ats ai ii (Top : ctx) |- ty
= Ctx ats ai ii ctx |- ty
Ctx _ _ _ (Bottom : _ctx) |- _ty
= return True
Ctx ats _ai _ii [] |- Var a
| Set.member a ats
= return True
Ctx _ats _ai _ii (x : _ctx) |- ty
| x == ty
= return True
Ctx ats ai ii (Var a : ctx) |- ty
= Ctx (Set.insert a ats) ai ii ctx |- ty
Ctx ats ai ii ctx |- (a :=>: b)
= Ctx ats ai ii (a : ctx) |- b
Ctx ats ai ii ((x :/\: y) : ctx) |- ty
= Ctx ats ai ii (x : y : ctx) |- ty
Ctx ats ai ii ((Top :=>: c) : ctx) |- ty
= Ctx ats ai ii (c : ctx) |- ty
Ctx ats ai ii ((Bottom :=>: _) : ctx) |- ty
= Ctx ats ai ii ctx |- ty
Ctx ats ai ii ((a :/\: b :=>: c) : ctx) |- ty
= Ctx ats ai ii ((a :=>: b :=>: c) : ctx) |- ty
Ctx ats ai ii ((a :\/: b :=>: c) : ctx) |- ty = do
p <- Var <$> freshVar
Ctx ats ai ii ((p :=>: c) : (a :=>: p) : (b :=>: p) : ctx) |- ty
Ctx ats ai ii (((a :=>: b) :=>: c) : ctx) |- ty
= Ctx ats ai (Set.insert (ImplImpl a b c) ii) ctx |- ty
Ctx ats ai ii ((Var x :=>: b) : ctx) |- ty
= Ctx ats (Set.insert (AtomImpl x b) ai) ii ctx |- ty
Ctx ats ai ii ((x :\/: y) : ctx) |- ty
= Ctx ats ai ii (x : ctx) |- ty
.&& Ctx ats ai ii (y : ctx) |- ty
ctx |- (a :/\: b)
= ctx |- a
.&& ctx |- b
Ctx ats ai ii [] |- ty
| ((y, ai') : _) <- match
= Ctx ats ai' ii [y] |- ty
| not (null rest) = iter rest
where
match =
[ (y, Set.delete ai' ai)
| ai'@(AtomImpl x y) <- Set.toList ai
, x `Set.member` ats
]
iter [] = return False
iter (Right (ctx', ty') : rest') = do
res <- ctx' |- ty'
if res
then return True
else iter rest'
iter (Left (ctxa, a, ctxb, b) : rest') = do
res <- ctxa |- a .&& ctxb |- b
if res
then return True
else iter rest'
rest = disj ++ implImpl
implImpl =
[ Left (Ctx ats ai ii' [x, y :=>: z], y, Ctx ats ai ii' [z], ty)
| entry@(ImplImpl x y z) <- Set.toList ii
, let ii' = Set.delete entry ii
]
disj = case ty of
a :\/: b ->
[ Right (Ctx ats ai ii [], a)
, Right (Ctx ats ai ii [], b)
]
_ -> []
Ctx _ _ _ [] |- (_ :\/: _)
= error "panic! @proofSearch should be matched before"
Ctx _ _ _ [] |- Var _
= return False
Ctx _ _ _ [] |- Bottom
= return False
data Am a
= L !Int
| R a
deriving (Eq, Ord, Show)
data Ctx a = Ctx
{ ctxAtoms :: Set (Am a)
, ctxAtomImpl :: Set (AtomImpl a)
, ctxImplImpl :: Set (ImplImpl a)
, ctxHypothesis :: [Expr (Am a)]
}
deriving Show
emptyCtx :: Ctx l
emptyCtx = Ctx Set.empty Set.empty Set.empty []
data AtomImpl a = AtomImpl (Am a) (Expr (Am a))
deriving (Eq, Ord, Show)
data ImplImpl a = ImplImpl !(Expr (Am a)) !(Expr (Am a)) !(Expr (Am a))
deriving (Eq, Ord, Show)