logic-classes-0.47: Data/Logic/Types/FirstOrderPublic.hs
{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GeneralizedNewtypeDeriving,
MultiParamTypeClasses, RankNTypes, ScopedTypeVariables, TemplateHaskell, UndecidableInstances #-}
{-# OPTIONS -Wwarn -fno-warn-orphans #-}
-- |An instance of FirstOrderFormula which implements Eq and Ord by comparing
-- after conversion to normal form. This helps us notice that formula which
-- only differ in ways that preserve identity, e.g. swapped arguments to a
-- commutative operator.
module Data.Logic.Types.FirstOrderPublic
( Formula(..)
, Bijection(..)
) where
import Data.Data (Data)
import Data.Logic.Classes.Arity (Arity)
import Data.Logic.Classes.Boolean (Boolean(..))
import Data.Logic.Classes.FirstOrder (FirstOrderFormula(..))
import qualified Data.Logic.Types.FirstOrder as N
import Data.Logic.Classes.Logic (Logic(..))
import Data.Logic.Classes.Negatable (Negatable(..))
import Data.Logic.Classes.Pred (Pred(..))
import Data.Logic.Classes.Propositional (Combine(..))
import Data.Logic.Classes.Skolem (Skolem(..))
import Data.Logic.Classes.Term (Term(..), )
import Data.Logic.Classes.Variable (Variable)
import Data.Logic.Normal.Implicative (implicativeNormalForm, ImplicativeForm)
import Data.Logic.Normal.Skolem (runNormal)
import Data.SafeCopy (base, deriveSafeCopy)
import Data.Set (Set)
import Data.Typeable (Typeable)
import Happstack.Data (deriveNewData)
-- |Convert between the public and internal representations.
class Bijection p i where
public :: i -> p
intern :: p -> i
-- |The new Formula type is just a wrapper around the Native instance
-- (which eventually should be renamed the Internal instance.) No
-- derived Eq or Ord instances.
data Formula v p f = Formula {unFormula :: N.Formula v p f} deriving (Read, Data, Typeable)
instance Bijection (Formula v p f) (N.Formula v p f) where
public = Formula
intern = unFormula
instance Bijection (Combine (Formula v p f)) (Combine (N.Formula v p f)) where
public (BinOp x op y) = BinOp (public x) op (public y)
public ((:~:) x) = (:~:) (public x)
intern (BinOp x op y) = BinOp (intern x) op (intern y)
intern ((:~:) x) = (:~:) (intern x)
instance Negatable (Formula v p f) where
negated = negated . unFormula
(.~.) = Formula . (.~.) . unFormula
instance (Variable v, Show v, Ord v, Data v,
Arity p, Boolean p, Show p, Ord p, Data p,
Skolem f, Show f, Ord f, Data f) => Logic (Formula v p f) where
x .<=>. y = Formula $ (unFormula x) .<=>. (unFormula y)
x .=>. y = Formula $ (unFormula x) .=>. (unFormula y)
x .|. y = Formula $ (unFormula x) .|. (unFormula y)
x .&. y = Formula $ (unFormula x) .&. (unFormula y)
instance (Arity p, Variable v, Skolem f, Boolean p,
Show p, Show v, Show f,
Ord f, Ord v, Ord p,
Data p, Data v, Data f) => Show (Formula v p f) where
showsPrec n x = showsPrec n (unFormula x)
instance (Variable v, Show v, Ord v, Data v,
Show p, Ord p, Data p, Boolean p, Arity p,
Skolem f, Show f, Ord f, Data f) => Pred p (N.PTerm v f) (Formula v p f) where
pApp0 p = (public :: N.Formula v p f -> Formula v p f) $ pApp0 p
pApp1 p t1 = (public :: N.Formula v p f -> Formula v p f) $ pApp1 p (t1)
pApp2 p t1 t2 = (public :: N.Formula v p f -> Formula v p f) $ pApp2 p (t1) (t2)
pApp3 p t1 t2 t3 = (public :: N.Formula v p f -> Formula v p f) $ pApp3 (p) (t1) (t2) (t3)
pApp4 p t1 t2 t3 t4 = (public :: N.Formula v p f -> Formula v p f) $ pApp4 (p) (t1) (t2) (t3) (t4)
pApp5 p t1 t2 t3 t4 t5 = (public :: N.Formula v p f -> Formula v p f) $ pApp5 (p) (t1) (t2) (t3) (t4) (t5)
pApp6 p t1 t2 t3 t4 t5 t6 = (public :: N.Formula v p f -> Formula v p f) $ pApp6 (p) (t1) (t2) (t3) (t4) (t5) (t6)
pApp7 p t1 t2 t3 t4 t5 t6 t7 = (public :: N.Formula v p f -> Formula v p f) $ pApp7 (p) (t1) (t2) (t3) (t4) (t5) (t6) (t7)
t1 .=. t2 = (public :: N.Formula v p f -> Formula v p f) $ (t1) .=. (t2)
instance (Logic (Formula v p f), Term (N.PTerm v f) v f,
Show v,
Arity p, Boolean p, Ord p, Data p, Show p,
Ord f, Show f) => FirstOrderFormula (Formula v p f) (N.PTerm v f) v p f where
for_all v x = public $ for_all v (intern x :: N.Formula v p f)
exists v x = public $ exists v (intern x :: N.Formula v p f)
foldFirstOrder q c p f = foldFirstOrder q' c' p (intern f :: N.Formula v p f)
where q' quant v form = q quant v (public form)
c' x = c (public x)
zipFirstOrder q c p f1 f2 = zipFirstOrder q' c' p (intern f1 :: N.Formula v p f) (intern f2 :: N.Formula v p f)
where q' q1 v1 f1' q2 v2 f2' = q q1 v1 (public f1') q2 v2 (public f2')
c' combine1 combine2 = c (public combine1) (public combine2)
-- |Here are the magic Ord and Eq instances
instance ({- FirstOrderFormula (Formula v p f) (N.PTerm v f) v p f,
Literal (N.Formula v p f) (N.PTerm v f) v p f,
FirstOrderFormula (N.Formula v p f) (N.PTerm v f) v p f, -}
Data v, Data f, Data p,
Ord v, Ord p, Ord f,
Show v, Show p, Show f,
Arity p, Boolean p, Skolem f, Variable v,
Ord (N.Formula v p f)) => Ord (Formula v p f) where
compare a b =
let (a' :: Set (ImplicativeForm (N.Formula v p f))) = runNormal (implicativeNormalForm (intern a :: N.Formula v p f))
(b' :: Set (ImplicativeForm (N.Formula v p f))) = runNormal (implicativeNormalForm (intern b :: N.Formula v p f)) in
case compare a' b' of
EQ -> EQ
x -> {- if isRenameOf a' b' then EQ else -} x
instance (FirstOrderFormula (Formula v p f) (N.PTerm v f) v p f) => Eq (Formula v p f) where
a == b = compare a b == EQ
$(deriveSafeCopy 1 'base ''Formula)
$(deriveNewData [''Formula])