connections-0.0.3: src/Data/Semigroup/Meet.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.Semigroup.Meet (
type (-)
, module Data.Semigroup.Meet
) where
import Control.Applicative
import Data.Bool
import Data.Either
import Data.Fixed
import Data.Int
import Data.Maybe
import Data.Prd
import Data.Ratio
import Data.Semigroup
import Data.Semigroup.Additive
import Data.Semigroup.Multiplicative
import Data.Word
import GHC.Generics (Generic)
import Numeric.Natural
import Prelude
( Eq(..), Ord, Show, Ordering(..), Applicative(..), Functor(..)
, Monoid(..), Semigroup(..), (.), ($), (<$>), Integer)
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Prelude as P
infixr 6 ∧
-- | Meet operation on a semilattice.
--
-- >>> (> (0::Int)) ∧ ((< 10) ∨ (== 15)) $ 15
-- True
--
(∧) :: (Meet-Semigroup) a => a -> a -> a
a ∧ b = unMeet (Meet a <> Meet b)
{-# INLINE (∧) #-}
top :: (Meet-Monoid) a => a
top = unMeet mempty
{-# INLINE top #-}
-- | The partial ordering induced by the meet-semilattice structure.
--
-- Normally when /a/ implements 'Prd' we should have:
-- @ 'meetLeq' x y ≡ x '<=' y @
--
meetLeq :: Eq a => (Meet-Semigroup) a => a -> a -> Bool
meetLeq x y = x ∧ y == x
-- | The partial ordering induced by the meet-semilattice structure.
--
-- Normally when /a/ implements 'Prd' we should have:
-- @ 'meetGeq' x y ≡ x '>=' y @
--
meetGeq :: Eq a => (Meet-Semigroup) a => a -> a -> Bool
meetGeq x y = x ∧ y == y
-- | Partial version of 'Data.Ord.compare'.
--
-- Normally when /a/ implements 'Prd' we should have:
-- @ 'pcompareJoin' x y ≡ 'pcompare' x y @
--
pcompareMeet :: Eq a => (Meet-Semigroup) a => a -> a -> Maybe Ordering
pcompareMeet x y
| x == y = Just EQ
| x ∧ y == x && x /= y = Just LT
| x ∧ y == y && x /= y = Just GT
| otherwise = Nothing
type MeetSemilattice a = (Prd a, (Meet-Semigroup) a)
newtype Meet a = Meet { unMeet :: a } deriving (Eq, Generic, Ord, Show, Functor)
instance Applicative Meet where
pure = Meet
Meet f <*> Meet a = Meet (f a)
-- >>> Min 1 ∧ Min 2 :: Min Int
-- Min {getMin = 1}
instance Semigroup (Min a) => Semigroup (Meet (Min a)) where
(<>) = liftA2 (<>)
instance (Meet-Semigroup) (Min a) => Semigroup (Additive (Min a)) where
(<>) = liftA2 (∧)
instance (Meet-Monoid) (Min a) => Monoid (Additive (Min a)) where
mempty = pure top
-- workaround for poorly specified entailment: instance (Ord a, Bounded a) => Monoid (Min a)
-- >>> zero :: Min Natural
-- Min {getMin = 0}
instance (Maximal a, Semigroup (Min a)) => Monoid (Meet (Min a)) where
mempty = pure $ Min maximal
---------------------------------------------------------------------
-- Semigroup Instances
---------------------------------------------------------------------
--instance ((Meet-Semigroup) a, Maximal a) => Monoid (Meet a) where
-- mempty = Meet maximal
-- MaxTimes Predioid
instance (Meet-Semigroup) a => Semigroup (Meet (Max a)) where
Meet a <> Meet b = Meet $ liftA2 (∧) a b
-- MaxTimes Dioid
instance (Meet-Monoid) a => Monoid (Meet (Max a)) where
mempty = Meet $ pure top
instance ((Meet-Semigroup) a, (Meet-Semigroup) b) => Semigroup (Meet (a, b)) where
Meet (x1, y1) <> Meet (x2, y2) = Meet (x1 ∧ x2, y1 ∧ y2)
instance (Meet-Semigroup) b => Semigroup (Meet (a -> b)) where
(<>) = liftA2 . liftA2 $ (∧)
{-# INLINE (<>) #-}
instance (Meet-Monoid) b => Monoid (Meet (a -> b)) where
mempty = pure . pure $ top
instance (Meet-Semigroup) a => Semigroup (Meet (Maybe a)) where
Meet Nothing <> _ = Meet Nothing
Meet (Just{}) <> Meet Nothing = Meet Nothing
Meet (Just x) <> Meet (Just y) = Meet . Just $ x ∧ y
-- Mul a <> Mul b = Mul $ liftA2 (∧) a b
instance (Meet-Monoid) a => Monoid (Meet (Maybe a)) where
mempty = Meet $ pure top
instance ((Meet-Semigroup) a, (Meet-Semigroup) b) => Semigroup (Meet (Either a b)) where
Meet (Right x) <> Meet (Right y) = Meet . Right $ x ∧ y
Meet (Right{}) <> y = y
Meet (Left x) <> Meet (Left y) = Meet . Left $ x ∧ y
Meet (x@Left{}) <> _ = Meet x
instance Ord a => Semigroup (Meet (Set.Set a)) where
(<>) = liftA2 Set.intersection
instance (Ord k, (Meet-Semigroup) a) => Semigroup (Meet (Map.Map k a)) where
(<>) = liftA2 (Map.intersectionWith (∧))
instance (Meet-Semigroup) a => Semigroup (Meet (IntMap.IntMap a)) where
(<>) = liftA2 (IntMap.intersectionWith (∧))
instance Semigroup (Meet IntSet.IntSet) where
(<>) = liftA2 IntSet.intersection
{-
instance (Ord k, (Meet-Monoid) k, (Meet-Monoid) a) => Monoid (Meet (Map.Map k a)) where
mempty = Meet $ Map.singleton top top
instance (Meet-Monoid) a => Monoid (Meet (IntMap.IntMap a)) where
mempty = Meet $ IntMap.singleton 0 top --TODO check
-}
{-
instance Monoid a => Semiring (Seq.Seq a) where
(*) = liftA2 (<>)
{-# INLINE (*) #-}
fromBoolean = fromBooleanDef $ Seq.singleton mempty
instance (Ord k, Monoid k, Monoid a) => Semiring (Map.Map k a) where
xs * ys = foldMap (flip Map.map xs . (<>)) ys
{-# INLINE (*) #-}
fromBoolean = fromBooleanDef $ Map.singleton mempty mempty
instance Monoid a => Semiring (IntMap.IntMap a) where
xs * ys = foldMap (flip IntMap.map xs . (<>)) ys
{-# INLINE (*) #-}
fromBoolean = fromBooleanDef $ IntMap.singleton 0 mempty
-}
{-
instance Semigroup (Meet ()) where
_ <> _ = pure ()
{-# INLINE (<>) #-}
instance Monoid (Meet ()) where
mempty = pure ()
{-# INLINE mempty #-}
instance Semigroup (Meet Bool) where
a <> b = (P.&&) <$> a <*> b
{-# INLINE (<>) #-}
instance Monoid (Meet Bool) where
mempty = pure True
{-# INLINE mempty #-}
-}
#define deriveMeetSemigroup(ty) \
instance Semigroup (Meet ty) where { \
a <> b = (P.min) <$> a <*> b \
; {-# INLINE (<>) #-} \
}
deriveMeetSemigroup(())
deriveMeetSemigroup(Bool)
deriveMeetSemigroup(Int)
deriveMeetSemigroup(Int8)
deriveMeetSemigroup(Int16)
deriveMeetSemigroup(Int32)
deriveMeetSemigroup(Int64)
deriveMeetSemigroup(Integer)
deriveMeetSemigroup(Word)
deriveMeetSemigroup(Word8)
deriveMeetSemigroup(Word16)
deriveMeetSemigroup(Word32)
deriveMeetSemigroup(Word64)
deriveMeetSemigroup(Natural)
deriveMeetSemigroup(Uni)
deriveMeetSemigroup(Deci)
deriveMeetSemigroup(Centi)
deriveMeetSemigroup(Milli)
deriveMeetSemigroup(Micro)
deriveMeetSemigroup(Nano)
deriveMeetSemigroup(Pico)
deriveMeetSemigroup(Rational)
deriveMeetSemigroup((Ratio Natural))
#define deriveMeetMonoid(ty) \
instance Monoid (Meet ty) where { \
mempty = pure maximal \
; {-# INLINE mempty #-} \
}
deriveMeetMonoid(())
deriveMeetMonoid(Bool)
deriveMeetMonoid(Int)
deriveMeetMonoid(Int8)
deriveMeetMonoid(Int16)
deriveMeetMonoid(Int32)
deriveMeetMonoid(Int64)
deriveMeetMonoid(Word)
deriveMeetMonoid(Word8)
deriveMeetMonoid(Word16)
deriveMeetMonoid(Word32)
deriveMeetMonoid(Word64)