#if __GLASGOW_HASKELL__ >= 707 && __GLASGOW_HASKELL__ < 709
#endif
module Algebra.Lattice (
JoinSemiLattice(..), MeetSemiLattice(..), Lattice,
joinLeq, joins1, meetLeq, meets1,
BoundedJoinSemiLattice(..), BoundedMeetSemiLattice(..), BoundedLattice,
joins, meets,
Meet(..), Join(..),
lfp, lfpFrom, unsafeLfp,
gfp, gfpFrom, unsafeGfp,
) where
import qualified Algebra.PartialOrd as PO
import Data.Universe.Class
#if MIN_VERSION_base(4,8,0)
#else
import Data.Foldable (Foldable, foldMap)
#endif
import Data.Proxy
import Data.Semigroup
import Data.Tagged
import Data.Void
import qualified Data.IntMap as IM
import qualified Data.IntSet as IS
import qualified Data.Map as M
import qualified Data.Set as S
import Data.Hashable
import qualified Data.HashSet as HS
import qualified Data.HashMap.Lazy as HM
import Data.Data
infixr 6 /\
infixr 5 \/
class JoinSemiLattice a where
(\/) :: a -> a -> a
(\/) = join
join :: a -> a -> a
join = (\/)
#if __GLASGOW_HASKELL__ >= 709
#endif
joinLeq :: (Eq a, JoinSemiLattice a) => a -> a -> Bool
joinLeq x y = (x \/ y) == y
joins1 :: JoinSemiLattice a => [a] -> a
joins1 = foldr1 (\/)
class MeetSemiLattice a where
(/\) :: a -> a -> a
(/\) = meet
meet :: a -> a -> a
meet = (/\)
#if __GLASGOW_HASKELL__ >= 709
#endif
meetLeq :: (Eq a, MeetSemiLattice a) => a -> a -> Bool
meetLeq x y = (x /\ y) == x
meets1 :: MeetSemiLattice a => [a] -> a
meets1 = foldr1 (/\)
class (JoinSemiLattice a, MeetSemiLattice a) => Lattice a where
class JoinSemiLattice a => BoundedJoinSemiLattice a where
bottom :: a
joins :: (BoundedJoinSemiLattice a, Foldable f) => f a -> a
joins = getJoin . foldMap Join
class MeetSemiLattice a => BoundedMeetSemiLattice a where
top :: a
meets :: (BoundedMeetSemiLattice a, Foldable f) => f a -> a
meets = getMeet . foldMap Meet
class (Lattice a, BoundedJoinSemiLattice a, BoundedMeetSemiLattice a) => BoundedLattice a where
instance Ord a => JoinSemiLattice (S.Set a) where
(\/) = S.union
instance Ord a => MeetSemiLattice (S.Set a) where
(/\) = S.intersection
instance Ord a => Lattice (S.Set a) where
instance Ord a => BoundedJoinSemiLattice (S.Set a) where
bottom = S.empty
instance (Ord a, Finite a) => BoundedMeetSemiLattice (S.Set a) where
top = S.fromList universeF
instance (Ord a, Finite a) => BoundedLattice (S.Set a) where
instance JoinSemiLattice IS.IntSet where
(\/) = IS.union
instance BoundedJoinSemiLattice IS.IntSet where
bottom = IS.empty
instance (Eq a, Hashable a) => JoinSemiLattice (HS.HashSet a) where
(\/) = HS.union
instance (Eq a, Hashable a) => MeetSemiLattice (HS.HashSet a) where
(/\) = HS.intersection
instance (Eq a, Hashable a) => BoundedJoinSemiLattice (HS.HashSet a) where
bottom = HS.empty
instance (Ord k, JoinSemiLattice v) => JoinSemiLattice (M.Map k v) where
(\/) = M.unionWith (\/)
instance (Ord k, MeetSemiLattice v) => MeetSemiLattice (M.Map k v) where
(/\) = M.intersectionWith (/\)
instance (Ord k, Lattice v) => Lattice (M.Map k v) where
instance (Ord k, JoinSemiLattice v) => BoundedJoinSemiLattice (M.Map k v) where
bottom = M.empty
instance (Ord k, Finite k, BoundedMeetSemiLattice v) => BoundedMeetSemiLattice (M.Map k v) where
top = M.fromList (universeF `zip` repeat top)
instance (Ord k, Finite k, BoundedLattice v) => BoundedLattice (M.Map k v) where
instance JoinSemiLattice v => JoinSemiLattice (IM.IntMap v) where
(\/) = IM.unionWith (\/)
instance JoinSemiLattice v => BoundedJoinSemiLattice (IM.IntMap v) where
bottom = IM.empty
instance (Eq k, Hashable k) => JoinSemiLattice (HM.HashMap k v) where
(\/) = HM.union
instance (Eq k, Hashable k) => MeetSemiLattice (HM.HashMap k v) where
(/\) = HM.intersection
instance (Eq k, Hashable k) => BoundedJoinSemiLattice (HM.HashMap k v) where
bottom = HM.empty
instance JoinSemiLattice v => JoinSemiLattice (k -> v) where
f \/ g = \x -> f x \/ g x
instance MeetSemiLattice v => MeetSemiLattice (k -> v) where
f /\ g = \x -> f x /\ g x
instance Lattice v => Lattice (k -> v) where
instance BoundedJoinSemiLattice v => BoundedJoinSemiLattice (k -> v) where
bottom = const bottom
instance BoundedMeetSemiLattice v => BoundedMeetSemiLattice (k -> v) where
top = const top
instance BoundedLattice v => BoundedLattice (k -> v) where
instance JoinSemiLattice () where
_ \/ _ = ()
instance BoundedJoinSemiLattice () where
bottom = ()
instance MeetSemiLattice () where
_ /\ _ = ()
instance BoundedMeetSemiLattice () where
top = ()
instance Lattice () where
instance BoundedLattice () where
instance (JoinSemiLattice a, JoinSemiLattice b) => JoinSemiLattice (a, b) where
(x1, y1) \/ (x2, y2) = (x1 \/ x2, y1 \/ y2)
instance (MeetSemiLattice a, MeetSemiLattice b) => MeetSemiLattice (a, b) where
(x1, y1) /\ (x2, y2) = (x1 /\ x2, y1 /\ y2)
instance (Lattice a, Lattice b) => Lattice (a, b) where
instance (BoundedJoinSemiLattice a, BoundedJoinSemiLattice b) => BoundedJoinSemiLattice (a, b) where
bottom = (bottom, bottom)
instance (BoundedMeetSemiLattice a, BoundedMeetSemiLattice b) => BoundedMeetSemiLattice (a, b) where
top = (top, top)
instance (BoundedLattice a, BoundedLattice b) => BoundedLattice (a, b) where
instance JoinSemiLattice Bool where
(\/) = (||)
instance MeetSemiLattice Bool where
(/\) = (&&)
instance Lattice Bool where
instance BoundedJoinSemiLattice Bool where
bottom = False
instance BoundedMeetSemiLattice Bool where
top = True
instance BoundedLattice Bool where
newtype Join a = Join { getJoin :: a }
deriving (Eq, Ord, Read, Show, Bounded, Typeable, Data)
instance JoinSemiLattice a => Semigroup (Join a) where
Join a <> Join b = Join (a \/ b)
instance BoundedJoinSemiLattice a => Monoid (Join a) where
mempty = Join bottom
Join a `mappend` Join b = Join (a \/ b)
newtype Meet a = Meet { getMeet :: a }
deriving (Eq, Ord, Read, Show, Bounded, Typeable, Data)
instance MeetSemiLattice a => Semigroup (Meet a) where
Meet a <> Meet b = Meet (a /\ b)
instance BoundedMeetSemiLattice a => Monoid (Meet a) where
mempty = Meet top
Meet a `mappend` Meet b = Meet (a /\ b)
instance JoinSemiLattice All where
All a \/ All b = All $ a \/ b
instance BoundedJoinSemiLattice All where
bottom = All False
instance MeetSemiLattice All where
All a /\ All b = All $ a /\ b
instance BoundedMeetSemiLattice All where
top = All True
instance Lattice All where
instance BoundedLattice All where
instance JoinSemiLattice Any where
Any a \/ Any b = Any $ a \/ b
instance BoundedJoinSemiLattice Any where
bottom = Any False
instance MeetSemiLattice Any where
Any a /\ Any b = Any $ a /\ b
instance BoundedMeetSemiLattice Any where
top = Any True
instance Lattice Any where
instance BoundedLattice Any where
instance JoinSemiLattice a => JoinSemiLattice (Endo a) where
Endo a \/ Endo b = Endo $ a \/ b
instance BoundedJoinSemiLattice a => BoundedJoinSemiLattice (Endo a) where
bottom = Endo bottom
instance MeetSemiLattice a => MeetSemiLattice (Endo a) where
Endo a /\ Endo b = Endo $ a /\ b
instance BoundedMeetSemiLattice a => BoundedMeetSemiLattice (Endo a) where
top = Endo top
instance Lattice a => Lattice (Endo a) where
instance BoundedLattice a => BoundedLattice (Endo a) where
instance JoinSemiLattice a => JoinSemiLattice (Tagged t a) where
Tagged a \/ Tagged b = Tagged $ a \/ b
instance BoundedJoinSemiLattice a => BoundedJoinSemiLattice (Tagged t a) where
bottom = Tagged bottom
instance MeetSemiLattice a => MeetSemiLattice (Tagged t a) where
Tagged a /\ Tagged b = Tagged $ a /\ b
instance BoundedMeetSemiLattice a => BoundedMeetSemiLattice (Tagged t a) where
top = Tagged top
instance Lattice a => Lattice (Tagged t a) where
instance BoundedLattice a => BoundedLattice (Tagged t a) where
instance JoinSemiLattice (Proxy a) where
_ \/ _ = Proxy
instance BoundedJoinSemiLattice (Proxy a) where
bottom = Proxy
instance MeetSemiLattice (Proxy a) where
_ /\ _ = Proxy
instance BoundedMeetSemiLattice (Proxy a) where
top = Proxy
instance Lattice (Proxy a) where
instance BoundedLattice (Proxy a) where
instance JoinSemiLattice Void where
a \/ _ = a
instance MeetSemiLattice Void where
a /\ _ = a
instance Lattice Void where
unsafeLfp :: (Eq a, BoundedJoinSemiLattice a) => (a -> a) -> a
unsafeLfp = PO.unsafeLfpFrom bottom
lfp :: (Eq a, BoundedJoinSemiLattice a) => (a -> a) -> a
lfp = lfpFrom bottom
lfpFrom :: (Eq a, BoundedJoinSemiLattice a) => a -> (a -> a) -> a
lfpFrom init_x f = PO.unsafeLfpFrom init_x (\x -> f x \/ x)
unsafeGfp :: (Eq a, BoundedMeetSemiLattice a) => (a -> a) -> a
unsafeGfp = PO.unsafeGfpFrom top
gfp :: (Eq a, BoundedMeetSemiLattice a) => (a -> a) -> a
gfp = gfpFrom top
gfpFrom :: (Eq a, BoundedMeetSemiLattice a) => a -> (a -> a) -> a
gfpFrom init_x f = PO.unsafeGfpFrom init_x (\x -> f x /\ x)