{-# LANGUAGE CPP #-}
module Algebra.Heyting
(
HeytingAlgebra (..)
, implies
, (<=>)
, iff
, iff'
, toBoolean
, BooleanAlgebra
)
where
import Prelude hiding (not)
import qualified Prelude
import Control.Applicative (Const (..))
import Data.Functor.Identity (Identity (..))
import Data.Hashable (Hashable)
import Data.Proxy (Proxy (..))
import Data.Semigroup ( All (..)
, Any (..)
, Endo (..)
)
import Data.Tagged (Tagged (..))
import Data.Universe.Class (Finite, universe)
import qualified Data.Map as M
import Data.Set (Set)
import qualified Data.Set as Set
import qualified Data.HashMap.Lazy as HM
import qualified Data.HashSet as HS
import Algebra.Lattice ( BoundedJoinSemiLattice (..)
, BoundedMeetSemiLattice (..)
, BoundedLattice
, Meet (..)
, bottom
, top
, (/\)
, (\/)
)
import Algebra.Lattice.Dropped (Dropped (..))
import Algebra.Lattice.Lifted (Lifted (..))
import Algebra.Lattice.Levitated (Levitated)
import qualified Algebra.Lattice.Levitated as L
import Algebra.Lattice.Ordered (Ordered (..))
import Algebra.Lattice.Op (Op (..))
import Algebra.PartialOrd (leq)
class BoundedLattice a => HeytingAlgebra a where
(==>) :: a -> a -> a
(==>) a b = not a \/ b
not :: a -> a
not a = a ==> bottom
{-# MINIMAL (==>) | not #-}
infixr 4 ==>
implies :: HeytingAlgebra a => a -> a -> a
implies = (==>)
(<=>) :: HeytingAlgebra a => a -> a -> a
a <=> b = (a ==> b) /\ (b ==> a)
iff :: HeytingAlgebra a => a -> a -> a
iff = (<=>)
iff' :: (Eq a, HeytingAlgebra a) => a -> a -> Bool
iff' a b = Meet top `leq` Meet (iff a b)
toBoolean :: HeytingAlgebra a => a -> a
toBoolean = not . not
instance HeytingAlgebra Bool where
not = Prelude.not
instance HeytingAlgebra All where
All a ==> All b = All (a ==> b)
not (All a) = All (not a)
instance HeytingAlgebra Any where
Any a ==> Any b = Any (a ==> b)
not (Any a) = Any (not a)
instance HeytingAlgebra () where
_ ==> _ = ()
instance HeytingAlgebra (Proxy a) where
_ ==> _ = Proxy
instance HeytingAlgebra a => HeytingAlgebra (Tagged t a) where
Tagged a ==> Tagged b = Tagged (a ==> b)
instance HeytingAlgebra b => HeytingAlgebra (a -> b) where
f ==> g = \a -> f a ==> g a
#if MIN_VERSION_base(4,8,0)
instance HeytingAlgebra a => HeytingAlgebra (Identity a) where
(Identity a) ==> (Identity b) = Identity (a ==> b)
#endif
instance HeytingAlgebra a => HeytingAlgebra (Const a b) where
(Const a) ==> (Const b) = Const (a ==> b)
instance HeytingAlgebra a => HeytingAlgebra (Endo a) where
(Endo f) ==> (Endo g) = Endo (f ==> g)
instance (HeytingAlgebra a, HeytingAlgebra b) => HeytingAlgebra (a, b) where
(a0, b0) ==> (a1, b1) = (a0 ==> a1, b0 ==> b1)
instance (Eq a, HeytingAlgebra a) => HeytingAlgebra (Dropped a) where
(Drop a) ==> (Drop b) | Meet a `leq` Meet b = Top
| otherwise = Drop (a ==> b)
Top ==> a = a
_ ==> Top = Top
instance HeytingAlgebra a => HeytingAlgebra (Lifted a) where
(Lift a) ==> (Lift b) = Lift (a ==> b)
Bottom ==> _ = Lift top
_ ==> Bottom = Bottom
instance (Eq a, HeytingAlgebra a) => HeytingAlgebra (Levitated a) where
(L.Levitate a) ==> (L.Levitate b) | Meet a `leq` Meet b = L.Top
| otherwise = L.Levitate (a ==> b)
L.Top ==> a = a
_ ==> L.Top = L.Top
L.Bottom ==> _ = L.Top
_ ==> L.Bottom = L.Bottom
instance (Ord a, Bounded a) => HeytingAlgebra (Ordered a) where
Ordered a ==> Ordered b | a <= b = top
| otherwise = Ordered b
instance (Ord a, Finite a) => HeytingAlgebra (Set a) where
not a = Set.fromList universe `Set.difference` a
instance (Eq a, Finite a, Hashable a) => HeytingAlgebra (HS.HashSet a) where
not a = HS.fromList universe `HS.difference` a
instance (Ord k, Finite k, HeytingAlgebra v) => HeytingAlgebra (M.Map k v) where
#if __GLASOW_HASKELL__ >= 804
a ==> b =
Merge.merge
Merge.dropMissing
(Merge.mapMissing (\_ _ -> top))
(Merge.zipWithMatched (\_ -> (==>)))
a b
\/ M.fromList [(k, top) | k <- universe, not (M.member k a), not (M.member k b) ]
#else
a ==> b =
M.intersectionWith (==>) a b
`M.union` M.map (const top) (M.difference b a)
`M.union` M.fromList [(k, top) | k <- universe, not (M.member k a), not (M.member k b)]
#endif
instance (Eq k, Finite k, Hashable k, HeytingAlgebra v) => HeytingAlgebra (HM.HashMap k v) where
a ==> b = HM.intersectionWith (==>) a b
`HM.union` HM.map (const top) (HM.difference b a)
`HM.union` HM.fromList [(k, top) | k <- universe, not (HM.member k a), not (HM.member k b)]
class HeytingAlgebra a => BooleanAlgebra a
instance BooleanAlgebra Bool
instance BooleanAlgebra All
instance BooleanAlgebra Any
instance BooleanAlgebra ()
instance BooleanAlgebra (Proxy a)
instance BooleanAlgebra a => BooleanAlgebra (Tagged t a)
instance BooleanAlgebra b => BooleanAlgebra (a -> b)
#if MIN_VERSION_base(4,8,0)
instance BooleanAlgebra a => BooleanAlgebra (Identity a)
#endif
instance BooleanAlgebra a => BooleanAlgebra (Const a b)
instance BooleanAlgebra a => BooleanAlgebra (Endo a)
instance (BooleanAlgebra a, BooleanAlgebra b) => BooleanAlgebra (a, b)
instance (Ord a, Finite a) => BooleanAlgebra (Set a)
instance BooleanAlgebra a => HeytingAlgebra (Op a) where
(Op a) ==> (Op b) = Op (not a /\ b)
instance BooleanAlgebra a => BooleanAlgebra (Op a)