packages feed

logic-classes-0.44: Data/Logic/Types/Propositional.hs

{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses #-}
module Data.Logic.Types.Propositional where

import Data.Generics (Data, Typeable)
import Data.Logic.Classes.Negatable (Negatable(..))
import Data.Logic.Classes.Propositional (PropositionalFormula(..), Combine(..), BinOp(..))
import Data.Logic.Classes.Logic (Logic(..))
import Data.Logic.Classes.Boolean (Boolean(..))

-- | The range of a formula is {True, False} when it has no free variables.
data Formula atom
    = Combine (Combine (Formula atom))
    | Atom atom
    -- Note that a derived Eq instance is not going to tell us that
    -- a&b is equal to b&a, let alone that ~(a&b) equals (~a)|(~b).
    deriving (Eq,Ord,Read,Data,Typeable)

instance Negatable (Formula atom) where
    (.~.) (Combine ((:~:) (Combine ((:~:) x)))) = (.~.) x
    (.~.) (Combine ((:~:) x)) = x
    (.~.) x = Combine ((:~:) x)
    negated (Combine ((:~:) x)) = not (negated x)
    negated _ = False

instance Ord atom => Logic (Formula atom) where
    x .<=>. y = Combine (BinOp  x (:<=>:) y)
    x .=>.  y = Combine (BinOp  x (:=>:)  y)
    x .|.   y = Combine (BinOp  x (:|:)   y)
    x .&.   y = Combine (BinOp  x (:&:)   y)

instance Boolean atom => Boolean (Formula atom) where
    fromBool = Atom . fromBool

instance (Boolean atom, Ord atom) => PropositionalFormula (Formula atom) atom where
    atomic a = Atom a
    foldPropositional c a formula =
        case formula of
          Combine x -> c x
          Atom x -> a x
{-
    asBool (Atom x) =
        if x == fromBool True
        then Just True
        else if x == fromBool False
             then Just False
             else Nothing
    asBool (Combine _) = Nothing
-}