-- {-# LANGUAGE #-} {-# OPTIONS_GHC -Wall #-} ---------------------------------------------------------------------- -- | -- Module : Data.Glb -- Copyright : (c) Conal Elliott 2010 -- License : BSD3 -- -- Maintainer : conal@conal.net -- Stability : experimental -- -- Greatest lower bound ---------------------------------------------------------------------- module Data.Glb (HasGlb(..),glbBottom,flatGlb) where import Control.Applicative (liftA2) import Data.Repr -- | Types that support information intersection ('glb') class HasGlb a where -- | Greatest lower information bound. Intersects information available -- from each argument. glb :: a -> a -> a -- | n-ary 'glb' for n > 0. Defaults to @foldr1 glb@. Unlike @lub@, we -- have no unit for 'glb'. glbs1 :: [a] -> a glbs1 = foldr1 glb -- | Bottom for a 'glb'. In the form of @error \"glb: bottom (\)\"@, -- though not really an error. glbBottom :: String -> a glbBottom msg = error $ "glb: bottom (" ++ msg ++ ")" -- | 'glb' on flat types with equality. Gives bottom for unequal -- arguments. flatGlb :: Eq a => a -> a -> a flatGlb a b | a == b = a | otherwise = glbBottom "flat & unequal" -- Flat types: instance HasGlb () where glb = flatGlb instance HasGlb Bool where glb = flatGlb instance HasGlb Char where glb = flatGlb instance HasGlb Int where glb = flatGlb instance HasGlb Integer where glb = flatGlb instance HasGlb Float where glb = flatGlb instance HasGlb Double where glb = flatGlb -- ... instance (HasGlb a, HasGlb b) => HasGlb (a,b) where (a,b) `glb` (a',b') = (a `glb` a', b `glb` b') instance HasGlb b => HasGlb (a -> b) where glb = liftA2 glb instance (HasGlb a, HasGlb b) => HasGlb (Either a b) where Left a `glb` Left a' = Left (a `glb` a') Right b `glb` Right b' = Right (b `glb` b') _ `glb` _ = glbBottom "Left/Right mismatch" -- 'glb' on representations repGlb :: (HasRepr a v, HasGlb v) => a -> a -> a repGlb = onRepr2 glb -- instance (HasRepr t v, HasGlb v) => HasGlb t where -- glb = repGlb -- For instance, instance HasGlb a => HasGlb (Maybe a) where glb = repGlb instance HasGlb a => HasGlb [a] where glb = repGlb {- -- Examples -- It takes care to check that some of these examples are computed -- correctly, since printing stops at the first error. For instance, ask -- for t5!!1 . t1,t2 :: Int t1 = 6 `glb` 8 -- _|_ t2 = 7 `glb` 7 -- 7 t3,t4 :: (Int,Int) t3 = (3,4) `glb` (4,5) -- (_|_,_|_) t4 = (3,4) `glb` (3,5) -- (3,_|_) t5 :: [Int] t5 = [2,3,5] `glb` [1,3] -- _|_:3:_|_ -}