{-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} module Data.Semilattice.Top where import Data.Prd import Data.Prd.Nan import Data.Semilattice import Data.Semifield import GHC.Generics (Generic, Generic1) import Prelude hiding (Ord(..), Bounded) type Bottom a = Maybe a type Bounded a = Bottom (Top a) type Lifted a = Nan (Top a) type Lowered a = Nan (Bottom a) type Extended a = Nan (Bounded a) data Top a = Fin a | Top deriving (Show, Generic, Generic1, Functor, Foldable, Traversable) -- analagous to Maybe Semigroup instance instance Semigroup a => Semigroup (Top a) where Top <> _ = Top _ <> Top = Top Fin x <> Fin y = Fin $ x <> y instance Monoid a => Monoid (Top a) where mempty = Fin mempty instance Prd a => Prd (Top a) where _ <= Top = True Top <= _ = False Fin a <= Fin b = a <= b instance Minimal a => Minimal (Top a) where minimal = Fin minimal instance Prd a => Maximal (Top a) where maximal = Top -- analagous to Maybe (Meet-Semigroup) instance instance (Join-Semigroup) a => Semigroup (Join (Top a)) where Join Top <> _ = Join Top Join (Fin{}) <> Join Top = Join Top Join (Fin x) <> Join (Fin y) = Join . Fin $ x ∨ y -- analagous to Maybe (Meet-Monoid) instance instance (Join-Monoid) a => Monoid (Join (Top a)) where mempty = Join $ Fin bottom instance (Meet-Semigroup) a => Semigroup (Meet (Top a)) where Meet (Fin x) <> Meet (Fin y) = Meet . Fin $ x ∧ y Meet (x@Fin{}) <> _ = Meet x Meet Top <> y = y instance (Meet-Semigroup) a => Monoid (Meet (Top a)) where mempty = Meet Top instance Lattice a => Lattice (Top a) {- instance Covered (Top Float) where Bounded x <. Bounded y = shiftf 1 x == y instance Graded (Top Float) where rank (Bounded x) | ind x = 0 | otherwise = r where x' = floatInt32 x y' = floatInt32 ninf r = fromIntegral . abs $ x' - y' -} isTop :: Bounded a -> Bool isTop = bounded False (const False) True isBottom :: Bounded a -> Bool isBottom = bounded True (const False) False isFin :: Bounded a -> Bool isFin = bounded False (const True) False fin :: a -> Bounded a fin = Just . Fin toTop :: Prd a => LowerBoundedLattice b => (a -> b) -> Bounded a -> Top b toTop f = bounded (Fin bottom) (Fin . f) Top toBottom :: Prd a => UpperBoundedLattice b => (a -> b) -> Bounded a -> Bottom b toBottom f = bounded Nothing (Just . f) (Just top) topped :: (a -> b) -> b -> Top a -> b topped f _ (Fin a) = f a topped _ b Top = b lifted :: Semifield b => (a -> b) -> Lifted a -> b lifted f = nan' $ topped f pinf bounded :: b -> (a -> b) -> b -> Bounded a -> b bounded b _ _ Nothing = b bounded _ f _ (Just (Fin a)) = f a bounded _ _ b (Just Top) = b -- | Interpret @'Bounded' a@ using the 'BoundedLattice' of @a@. -- -- This map is monotone when /f/ is. -- bounded' :: BoundedLattice b => (a -> b) -> Bounded a -> b bounded' f = bounded bottom f top extended :: b -> b -> (a -> b) -> b -> Extended a -> b extended x y f z = nan x $ bounded y f z extended' :: Field b => (a -> b) -> Extended a -> b extended' f = extended anan ninf f pinf -- this is a monotone map liftTop :: Maximal a => (a -> b) -> a -> Top b liftTop f = g where g i | i =~ maximal = Top | otherwise = Fin $ f i liftTop' :: Maximal a => (a -> b) -> a -> Bounded b liftTop' f a = Just $ liftTop f a -- This map is a lattice morphism when /f/ is. liftBottom :: Minimal a => (a -> b) -> a -> Bottom b liftBottom f = g where g i | i =~ minimal = Nothing | otherwise = Just $ f i liftBottom' :: Minimal a => (a -> b) -> a -> Bounded b liftBottom' f = liftBottom (Fin . f) -- this is a monotone map liftBounded :: Bound a => (a -> b) -> a -> Bounded b liftBounded f = liftBottom (liftTop f) -- Lift all exceptional values liftExtended :: Bound a => Field a => (a -> b) -> a -> Extended b liftExtended f = liftNan (liftBounded f)