module Data.Lattice where import Data.Function import Data.Set (Set) import qualified Data.Set as Set import Data.Map (Map) import qualified Data.Map as Map import Data.PartialOrder class Lattice a where lbot :: a ltop :: a ljoin :: a -> a -> a lmeet :: a -> a -> a instance Lattice () where lbot = () ltop = () ljoin _ _ = () lmeet _ _ = () instance (Lattice a, Lattice b) => Lattice (Either a b) where lbot = Left lbot ltop = Right ltop ljoin (Left a) (Left b) = Left $ ljoin a b ljoin (Left _) x@(Right _) = x ljoin x@(Right _) (Left _) = x ljoin (Right a) (Right b) = Right $ ljoin a b lmeet (Left a) (Left b) = Left $ lmeet a b lmeet x@(Left _) (Right _) = x lmeet (Right _) x@(Left _) = x lmeet (Right a) (Right b) = Right $ lmeet a b instance (Lattice a, Lattice b) => Lattice (a,b) where lbot = (lbot,lbot) ltop = (ltop,ltop) ljoin (a1,b1) (a2,b2) = (ljoin a1 a2,ljoin b1 b2) lmeet (a1,b1) (a2,b2) = (lmeet a1 a2,lmeet b1 b2) instance (Lattice a, Lattice b, Lattice c) => Lattice (a, b, c) where lbot = ungroup3 lbot ltop = ungroup3 ltop ljoin = ungroup3 .: ljoin `on` group3 lmeet = ungroup3 .: lmeet `on` group3 instance (Lattice a, Lattice b, Lattice c, Lattice d) => Lattice (a, b, c, d) where lbot = ungroup4 lbot ltop = ungroup4 ltop ljoin = ungroup4 .: ljoin `on` group4 lmeet = ungroup4 .: lmeet `on` group4 instance (Ord a) => Lattice (Set a) where lbot = Set.empty ltop = error "no representation of top set" ljoin = Set.union lmeet = Set.intersection instance (Ord k, Lattice v) => Lattice (Map k v) where lbot = Map.empty ltop = error "no representation of top map" ljoin = Map.unionWith ljoin lmeet = Map.intersectionWith lmeet lmeets :: (Lattice l) => [l] -> l lmeets = foldr lmeet ltop ljoins :: (Lattice l) => [l] -> l ljoins = foldr ljoin lbot