zsyntax-0.2.0.0: src/Zsyntax/Labelled/Rule/BipoleRelation.hs
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -Wno-unticked-promoted-constructors #-}
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
{-| Module of derived rule relations. -}
module Zsyntax.Labelled.Rule.BipoleRelation where
-- ( (:::)
-- , AnnLSequent
-- , IsFocusable
-- , BipoleRule
-- , focus
-- , implLeft
-- , copyRule
-- , implRight
-- ) where
import Data.Function (on)
import Data.Bifunctor (Bifunctor(..))
import Control.Monad (guard)
import Otter
import Data.Set (insert)
import Data.MultiSet (MultiSet, isSubsetOf, (\\), singleton)
import qualified Data.MultiSet as MS (insert)
import Zsyntax.Labelled.Rule.Interface
import Zsyntax.Labelled.Formula
import Zsyntax.Labelled.DerivationTerm
import Zsyntax.ReactionList
respects :: Ord a => ElemBase a -> RList (ElemBase a) (CtrlSet a) -> Bool
respects = respectsRList (\eb cty -> msRespectsCS (unEB eb) cty)
--------------------------------------------------------------------------------
-- | Type of derivation terms-decorated data.
data tm ::: pl = (:::) { _term :: tm, _payload :: pl } deriving (Eq, Ord, Show)
instance Bifunctor (:::) where
bimap f g (x ::: y) = f x ::: g y
-- | Type of labelled sequents that are annotated with a derivation term.
type AnnLSequent a l = DerivationTerm a l ::: LSequent a l
-- | A relation is an unbounded curried function with an annotated sequents as
-- input.
type BipoleRel a l = Rule (AnnLSequent a l)
-- | A rule of the derived rule calculus is a relation that has
-- derivation term-decorated sequents as both input and output.
type BipoleRule a l = Rule (AnnLSequent a l) (AnnLSequent a l)
-- | Predicate identifying those formula kinds that correspond to focusable
-- formulas.
class IsFocusable (k :: FKind) where
instance IsFocusable KAtom where
instance IsFocusable KConj where
type FocMatchRes a l = MatchRes a l FullXiEmptyResult
type DTFocMatchRes a l = DerivationTerm a l ::: FocMatchRes a l
type DTMatchRes a l actcase = DerivationTerm a l ::: MatchRes a l actcase
instance Subsumable s => Subsumable (tm ::: s) where
subsumes = subsumes `on` _payload
--------------------------------------------------------------------------------
-- | Given two multisets m1 and m2, it checks whether m1 is contained in m2,
-- and returns the rest of m2 if it is the case.
matchMultiSet :: Ord a => MultiSet a -> MultiSet a -> Maybe (MultiSet a)
matchMultiSet m1 m2 = if isSubsetOf m1 m2 then Just (m2 \\ m1) else Nothing
matchLinearCtxt
:: (Ord a, Ord l) => SchemaLCtxt a l -> LCtxt a l -> Maybe (LCtxt a l)
matchLinearCtxt (SLC slc) = matchMultiSet slc
matchSchema :: (Ord a, Ord l)
=> SSchema a l act -> AnnLSequent a l -> Maybe (DTMatchRes a l act)
matchSchema (SSEmptyGoal delta) (term ::: LS gamma delta' cty goal) = do
delta'' <- matchLinearCtxt delta delta'
pure (term ::: MRFullGoal gamma delta'' cty goal)
matchSchema (SSFullGoal delta cty cncl) (tm ::: LS gamma delta' cty' cncl') = do
delta'' <- matchLinearCtxt delta delta'
guard (cty == cty')
guard (cncl == cncl')
pure (tm ::: MREmptyGoal gamma delta'')
matchRel :: (Ord a, Ord l)
=> LCtxt a l -> ZetaXi a l act -> BipoleRel a l (DTMatchRes a l act)
matchRel delta zetaxi = match . matchSchema $
case zetaxi of
EmptyZetaXi -> SSEmptyGoal (SLC delta)
FullZetaXi cty g -> SSFullGoal (SLC delta) cty g
positiveFocalDispatch
:: (Ord l, Ord a)
=> LFormula k a l
-> BipoleRel a l (DTFocMatchRes a l)
positiveFocalDispatch fr = case fr of
Atom a -> pure (Init a ::: MREmptyGoal mempty (singleton (N fr)))
Impl {} -> match (matchSchema (SSFullGoal (SLC mempty) mempty (O fr)))
Conj f1 f2 l -> do
d ::: MREmptyGoal g1 d1 <- positiveFocalDispatch f1
d' ::: MREmptyGoal g2 d2 <- positiveFocalDispatch f2
pure $ ConjR d d' l ::: MREmptyGoal (g1 <> g2) (d1 <> d2)
leftActive
:: (Ord l, Ord a) => LCtxt a l -> [Opaque a l] -> ZetaXi a l act
-> BipoleRel a l (DTMatchRes a l act)
leftActive delta [] zetaxi = matchRel delta zetaxi
leftActive delta (O f : rest) zetaxi = withMaybeNeutral f
(leftActive (MS.insert (N f) delta) rest zetaxi)
(\(Conj f1 f2 _) -> do
d ::: res <- leftActive delta (O f2 : O f1 : rest) zetaxi
pure $ ConjL d ::: res)
focus :: (Ord l, Ord a, IsFocusable k) => LFormula k a l -> BipoleRule a l
focus formula = do
d ::: MREmptyGoal gamma delta <- positiveFocalDispatch formula
pure (d ::: LS gamma delta mempty (O formula))
implLeft :: (Ord l, Ord a) => LFormula KImpl a l -> BipoleRule a l
implLeft fr@(Impl f1 _ cty f2 _) = do
d ::: MREmptyGoal g1 d1 <- positiveFocalDispatch f1
d' ::: MRFullGoal g2 d2 cty' cl <- leftActive mempty [(O f2)] EmptyZetaXi
let b = lcBase d2
ext = extend b cty
guard (respects b cty)
pure $ ImplL d d' f2
::: LS (g1 <> g2) (MS.insert (N fr) (d1 <> d2)) (ext <> cty') cl
copyRule :: (Ord a, Ord l) => LAxiom a l -> BipoleRule a l
copyRule ax = let fr = axToFormula ax in case fr of
Impl f1 _ cty f2 _ -> do
d ::: MREmptyGoal g1 d1 <- positiveFocalDispatch f1
d' ::: MRFullGoal g2 d2 cty' cl <- leftActive mempty [(O f2)] EmptyZetaXi
let b = lcBase d2 ; ext = extend b cty
guard (respects b cty)
pure $ Copy (ImplL d d' f2) ax
::: LS (insert ax (g1 <> g2)) (d1 <> d2) (ext <> cty') cl
implRight :: (Ord a, Ord l) => LFormula KImpl a l -> BipoleRule a l
implRight fr@(Impl f1 eb cty f2 l) = do
tm ::: MREmptyGoal g d <- leftActive mempty [(O f1)] (FullZetaXi cty (O f2))
guard (lcBase d == eb)
pure $ ImplR tm fr eb cty l ::: LS g d mempty (O fr)