logic-classes-1.1: 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.Combine (Combinable(..), Combination(..))
import Data.Logic.Classes.Constants (Constants(..))
import Data.Logic.Classes.FirstOrder (FirstOrderFormula(..))
import Data.Logic.Classes.Negate (Negatable(..))
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, runNormal)
import qualified Data.Logic.Types.FirstOrder as N
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 (Data, Typeable)
instance Bijection (Formula v p f) (N.Formula v p f) where
public = Formula
intern = unFormula
instance Bijection (Combination (Formula v p f)) (Combination (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
negatePrivate = Formula . negatePrivate . unFormula
foldNegation normal inverted = foldNegation (normal . Formula) (inverted . Formula) . unFormula
instance (Constants (N.Formula v p f), Arity p, Constants p, Ord v, Ord p, Ord f, Variable v, Skolem f, Show v, Show p, Show f, Data v, Data f, Data p) => Constants (Formula v p f) where
fromBool = Formula . fromBool
instance (Constants (Formula v p f), Constants (N.Formula v p f),
Variable v, Show v, Ord v, Data v,
Arity p, Constants p, Show p, Ord p, Data p,
Skolem f, Show f, Ord f, Data f) => Combinable (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 (Constants (N.Formula v p f),
Arity p, Variable v, Skolem f, Constants 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 (Constants (Formula v p f), Constants (N.Formula v p f),
Combinable (Formula v p f), Term (N.PTerm v f) v f,
Show v,
Arity p, Constants p, Ord p, Data p, Show p,
Ord f, Show f) => FirstOrderFormula (Formula v p f) (N.Predicate p (N.PTerm v f)) v 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 qu co tf at f = foldFirstOrder qu' co' tf at (intern f :: N.Formula v p f)
where qu' quant v form = qu quant v (public form)
co' x = co (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)
-}
atomic = Formula . atomic
-- |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, -}
Constants (N.Predicate p (N.PTerm v f)),
Constants (Formula v p f), Constants (N.Formula v p f),
Data v, Data f, Data p,
Ord v, Ord p, Ord f,
Show v, Show p, Show f,
Arity p, Constants 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 (Arity p, Constants p, Skolem f, Show p, Show f, Ord p, Ord f, Data f, Data v, Data p, Constants (N.Predicate p (N.PTerm v f)),
FirstOrderFormula (Formula v p f) (N.Predicate p (N.PTerm v f)) v) => Eq (Formula v p f) where
a == b = compare a b == EQ
$(deriveSafeCopy 1 'base ''Formula)
$(deriveNewData [''Formula])