module SubHask.Algebra.Logic where import Control.Monad import qualified Prelude as P import Test.QuickCheck.Gen (suchThat,oneof) import SubHask.Algebra import SubHask.Category import SubHask.Compatibility.Base import SubHask.SubType import SubHask.Internal.Prelude import SubHask.TemplateHaskell.Deriving class (Ord r, Ring r) => OrdRing_ r instance (Ord r, Ring r) => OrdRing_ r -------------------------------------------------------------------------------- -- | The Goedel fuzzy logic is one of the simpler fuzzy logics. -- In particular, it is an example of a Heyting algebra that is not also a Boolean algebra. -- -- See the type Goedel = Goedel_ Rational newtype Goedel_ r = Goedel_ r deriveHierarchyFiltered ''Goedel_ [ ''Eq_ ] [ ''Arbitrary ] instance (OrdRing_ r, Arbitrary r) => Arbitrary (Goedel_ r) where arbitrary = fmap Goedel_ $ arbitrary `suchThat` ((>=0) && (<=1)) instance OrdRing_ r => POrd_ (Goedel_ r) where -- inf (Goedel_ r1) (Goedel_ r2) = Goedel_ $ max 0 (r1 + r2 - 1) inf (Goedel_ r1) (Goedel_ r2) = Goedel_ $ min r1 r2 -- inf (Goedel_ r1) (Goedel_ r2) = Goedel_ $ r1*r2 instance OrdRing_ r => Lattice_ (Goedel_ r) where -- sup (Goedel_ r1) (Goedel_ r2) = Goedel_ $ min 1 (r1 + r2) sup (Goedel_ r1) (Goedel_ r2) = Goedel_ $ max r1 r2 -- sup l1 l2 = not $ inf (not l1) (not l2) instance OrdRing_ r => Ord_ (Goedel_ r) instance OrdRing_ r => MinBound_ (Goedel_ r) where minBound = Goedel_ 0 instance OrdRing_ r => Bounded (Goedel_ r) where maxBound = Goedel_ 1 instance OrdRing_ r => Heyting (Goedel_ r) where -- (Goedel_ r1)==>(Goedel_ r2) = if r1 <= r2 then Goedel_ 1 else Goedel_ (1 - r1 + r2) (Goedel_ r1)==>(Goedel_ r2) = if r1 <= r2 then Goedel_ 1 else Goedel_ r2 --------------------------------------- -- | H3 is the smallest Heyting algebra that is not also a boolean algebra. -- In addition to true and false, there is a value to represent whether something's truth is unknown. -- AFAIK it has no real applications. -- -- See data H3 = HTrue | HFalse | HUnknown deriving (Read,Show) instance NFData H3 where rnf HTrue = () rnf HFalse = () rnf HUnknown = () instance Arbitrary H3 where arbitrary = oneof $ map return [HTrue, HFalse, HUnknown] type instance Logic H3 = Bool instance Eq_ H3 where HTrue == HTrue = True HFalse == HFalse = True HUnknown == HUnknown = True _ == _ = False instance POrd_ H3 where inf HTrue HTrue = HTrue inf HTrue HUnknown = HUnknown inf HUnknown HTrue = HUnknown inf HUnknown HUnknown = HUnknown inf _ _ = HFalse instance Lattice_ H3 where sup HFalse HFalse = HFalse sup HFalse HUnknown = HUnknown sup HUnknown HFalse = HUnknown sup HUnknown HUnknown = HUnknown sup _ _ = HTrue instance Ord_ H3 instance MinBound_ H3 where minBound = HFalse instance Bounded H3 where maxBound = HTrue instance Heyting H3 where _ ==> HTrue = HTrue HFalse ==> _ = HTrue HTrue ==> HFalse = HFalse HUnknown ==> HUnknown = HTrue HUnknown ==> HFalse = HFalse _ ==> _ = HUnknown --------------------------------------- -- | K3 stands for Kleene's 3-valued logic. -- In addition to true and false, there is a value to represent whether something's truth is unknown. -- K3 is an example of a logic that is neither Boolean nor Heyting. -- -- See . -- -- FIXME: We need a way to represent implication and negation for logics outside of the Lattice hierarchy. data K3 = KTrue | KFalse | KUnknown deriving (Read,Show) instance NFData K3 where rnf KTrue = () rnf KFalse = () rnf KUnknown = () instance Arbitrary K3 where arbitrary = oneof $ map return [KTrue, KFalse, KUnknown] type instance Logic K3 = Bool instance Eq_ K3 where KTrue == KTrue = True KFalse == KFalse = True KUnknown == KUnknown = True _ == _ = False instance POrd_ K3 where inf KTrue KTrue = KTrue inf KTrue KUnknown = KUnknown inf KUnknown KTrue = KUnknown inf KUnknown KUnknown = KUnknown inf _ _ = KFalse instance Lattice_ K3 where sup KFalse KFalse = KFalse sup KFalse KUnknown = KUnknown sup KUnknown KFalse = KUnknown sup KUnknown KUnknown = KUnknown sup _ _ = KTrue instance Ord_ K3 instance MinBound_ K3 where minBound = KFalse instance Bounded K3 where maxBound = KTrue -------------------------------------------------------------------------------- -- | A Boolean algebra is a special type of Ring. -- Their applications (set-like operations) tend to be very different than Rings, so it makes sense for the class hierarchies to be completely unrelated. -- The "Boolean2Ring" type, however, provides the correct transformation. newtype Boolean2Ring b = Boolean2Ring b deriveHierarchy ''Boolean2Ring [ ''Boolean ] mkBoolean2Ring :: Boolean b => b -> Boolean2Ring b mkBoolean2Ring = Boolean2Ring instance (IsMutable b, Boolean b, ValidLogic b) => Semigroup (Boolean2Ring b) where (Boolean2Ring b1)+(Boolean2Ring b2) = Boolean2Ring $ (b1 || b2) && not (b1 && b2) instance (IsMutable b, Boolean b, ValidLogic b) => Abelian (Boolean2Ring b) instance (IsMutable b, Boolean b, ValidLogic b) => Monoid (Boolean2Ring b) where zero = Boolean2Ring $ false instance (IsMutable b, Boolean b, ValidLogic b) => Cancellative (Boolean2Ring b) where (-)=(+) -- b1-b2 = b1+negate b2 instance (IsMutable b, Boolean b, ValidLogic b) => Group (Boolean2Ring b) where negate = id -- negate (Boolean2Ring b) = Boolean2Ring $ not b instance (IsMutable b, Boolean b, ValidLogic b) => Rg (Boolean2Ring b) where (Boolean2Ring b1)*(Boolean2Ring b2) = Boolean2Ring $ b1 && b2 instance (IsMutable b, Boolean b, ValidLogic b) => Rig (Boolean2Ring b) where one = Boolean2Ring $ true instance (IsMutable b, Boolean b, ValidLogic b) => Ring (Boolean2Ring b)