semirings 0.1.3.0 → 0.2.0.0
raw patch · 7 files changed
+499/−177 lines, 7 filesdep +taggeddep ~containersPVP ok
version bump matches the API change (PVP)
Dependencies added: tagged
Dependency ranges changed: containers
API changes (from Hackage documentation)
- Data.Semiring: instance (GHC.Base.Alternative f, Data.Semiring.Ring a) => Data.Semiring.Ring (Data.Monoid.Alt f a)
- Data.Semiring: instance (GHC.Base.Alternative f, Data.Semiring.Semiring a) => Data.Semiring.Semiring (Data.Monoid.Alt f a)
- Data.Semiring: instance (GHC.Base.Monoid a, Data.Semiring.Ring a) => Data.Semiring.Ring (Data.Monoid.Endo a)
- Data.Semiring: instance (GHC.Classes.Eq a, Data.Hashable.Class.Hashable a, Data.Semiring.Semiring a) => Data.Semiring.Semiring (Data.HashSet.HashSet a)
- Data.Semiring: instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k, Data.Semiring.Semiring k, Data.Semiring.Semiring v) => Data.Semiring.Semiring (Data.HashMap.Base.HashMap k v)
- Data.Semiring: instance (GHC.Classes.Ord a, Data.Semiring.Semiring a) => Data.Semiring.Semiring (Data.Set.Internal.Set a)
- Data.Semiring: instance (GHC.Classes.Ord a, Data.Semiring.Semiring a, Data.Semiring.Semiring b) => Data.Semiring.Semiring (Data.Map.Internal.Map a b)
- Data.Semiring: instance Data.Semiring.Ring a => Data.Semiring.Ring (Data.Monoid.Dual a)
- Data.Semiring: instance Data.Semiring.Ring a => Data.Semiring.Ring (Data.Monoid.Product a)
- Data.Semiring: instance Data.Semiring.Ring a => Data.Semiring.Ring (Data.Monoid.Sum a)
- Data.Semiring: instance Data.Semiring.Semiring Data.IntSet.Internal.IntSet
- Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.IntMap.Internal.IntMap a)
- Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Monoid.Dual a)
- Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Monoid.Product a)
- Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Monoid.Sum a)
- Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Sequence.Internal.Seq a)
- Data.Semiring: instance GHC.Base.Monoid a => Data.Semiring.Semiring (Data.Monoid.Endo a)
- Data.Semiring: prod :: (Foldable t, Semiring a) => t a -> a
- Data.Semiring: prod' :: (Foldable t, Semiring a) => t a -> a
- Data.Star: instance (GHC.Classes.Eq a, GHC.Base.Monoid a) => Data.Star.Star (Data.Monoid.Endo a)
+ Data.Semiring: Add :: a -> Add a
+ Data.Semiring: Mul :: a -> Mul a
+ Data.Semiring: [getAdd] :: Add a -> a
+ Data.Semiring: [getMul] :: Mul a -> a
+ Data.Semiring: instance (GHC.Classes.Eq a, Data.Hashable.Class.Hashable a, GHC.Base.Monoid a) => Data.Semiring.Semiring (Data.HashSet.HashSet a)
+ Data.Semiring: instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k, GHC.Base.Monoid k, Data.Semiring.Semiring v) => Data.Semiring.Semiring (Data.HashMap.Base.HashMap k v)
+ Data.Semiring: instance (GHC.Classes.Ord a, GHC.Base.Monoid a) => Data.Semiring.Semiring (Data.Set.Internal.Set a)
+ Data.Semiring: instance (GHC.Classes.Ord k, GHC.Base.Monoid k, Data.Semiring.Semiring v) => Data.Semiring.Semiring (Data.Map.Internal.Map k v)
+ Data.Semiring: instance Data.Foldable.Foldable Data.Semiring.Add
+ Data.Semiring: instance Data.Foldable.Foldable Data.Semiring.Mul
+ Data.Semiring: instance Data.Semiring.Ring a => Data.Semiring.Ring (Data.Semigroup.Internal.Dual a)
+ Data.Semiring: instance Data.Semiring.Ring a => Data.Semiring.Ring (Data.Semigroup.Internal.Product a)
+ Data.Semiring: instance Data.Semiring.Ring a => Data.Semiring.Ring (Data.Semigroup.Internal.Sum a)
+ Data.Semiring: instance Data.Semiring.Semiring (Data.Proxy.Proxy a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semigroup.Internal.Dual a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semigroup.Internal.Product a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semigroup.Internal.Sum a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semiring.Add a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semiring.Mul a)
+ Data.Semiring: instance Data.Semiring.Semiring a => GHC.Base.Monoid (Data.Semiring.Add a)
+ Data.Semiring: instance Data.Semiring.Semiring a => GHC.Base.Monoid (Data.Semiring.Mul a)
+ Data.Semiring: instance Data.Semiring.Semiring a => GHC.Base.Semigroup (Data.Semiring.Add a)
+ Data.Semiring: instance Data.Semiring.Semiring a => GHC.Base.Semigroup (Data.Semiring.Mul a)
+ Data.Semiring: instance Data.Traversable.Traversable Data.Semiring.Add
+ Data.Semiring: instance Data.Traversable.Traversable Data.Semiring.Mul
+ Data.Semiring: instance Foreign.Storable.Storable a => Foreign.Storable.Storable (Data.Semiring.Add a)
+ Data.Semiring: instance Foreign.Storable.Storable a => Foreign.Storable.Storable (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Base.Functor Data.Semiring.Add
+ Data.Semiring: instance GHC.Base.Functor Data.Semiring.Mul
+ Data.Semiring: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Enum.Enum a => GHC.Enum.Enum (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Enum.Enum a => GHC.Enum.Enum (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Generics.Generic (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Generics.Generic (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Generics.Generic1 Data.Semiring.Add
+ Data.Semiring: instance GHC.Generics.Generic1 Data.Semiring.Mul
+ Data.Semiring: instance GHC.Num.Num a => GHC.Num.Num (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Num.Num a => GHC.Num.Num (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Read.Read a => GHC.Read.Read (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Read.Read a => GHC.Read.Read (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Real.Fractional a => GHC.Real.Fractional (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Real.Fractional a => GHC.Real.Fractional (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Real.Real a => GHC.Real.Real (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Real.Real a => GHC.Real.Real (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Real.RealFrac a => GHC.Real.RealFrac (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Real.RealFrac a => GHC.Real.RealFrac (Data.Semiring.Mul a)
+ Data.Semiring: instance GHC.Show.Show a => GHC.Show.Show (Data.Semiring.Add a)
+ Data.Semiring: instance GHC.Show.Show a => GHC.Show.Show (Data.Semiring.Mul a)
+ Data.Semiring: newtype Add a
+ Data.Semiring: newtype Mul a
+ Data.Semiring: product :: (Foldable t, Semiring a) => t a -> a
+ Data.Semiring: product' :: (Foldable t, Semiring a) => t a -> a
+ Data.Semiring.Free: Free :: Map (Identity a) Natural -> Free a
+ Data.Semiring.Free: [getFree] :: Free a -> Map (Identity a) Natural
+ Data.Semiring.Free: instance (GHC.Classes.Ord a, GHC.Base.Monoid a) => Data.Semiring.Semiring (Data.Semiring.Free.Free a)
+ Data.Semiring.Free: instance (GHC.Classes.Ord a, GHC.Read.Read a) => GHC.Read.Read (Data.Semiring.Free.Free a)
+ Data.Semiring.Free: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Semiring.Free.Free a)
+ Data.Semiring.Free: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Semiring.Free.Free a)
+ Data.Semiring.Free: instance GHC.Show.Show a => GHC.Show.Show (Data.Semiring.Free.Free a)
+ Data.Semiring.Free: liftFree :: a -> Free a
+ Data.Semiring.Free: lowerFree :: Semiring s => Free s -> s
+ Data.Semiring.Free: newtype Free a
+ Data.Semiring.Free: runFree :: Semiring s => (a -> s) -> Free a -> s
+ Data.Star: instance Data.Star.Star (Data.Proxy.Proxy a)
Files
- CHANGELOG.md +8/−3
- Data/Semiring.hs +369/−146
- Data/Semiring/Free.hs +89/−0
- Data/Semiring/Generic.hs +2/−1
- Data/Star.hs +15/−16
- README.md +6/−4
- semirings.cabal +10/−7
CHANGELOG.md view
@@ -1,7 +1,12 @@-0.1.3.0: [2018.05.23]+0.2.0.0: [2018.07.23] ----------------------* remove dependency on `constrictor`.-* some doc fixes.+* Fixed the `Semiring` instances of `Set`, `HashSet`, `Vector`, `Storable Vector`, `Unboxed Vector`.+* Removed the `Semiring` instances of `Seq`, `Alt`, `Endo`.+* Added comprehensive test suite that tests all `Semiring` instances defined in Data.Semiring+* Added Free semiring (Data.Semiring.Free)+* Added newtypes: `Add`, `Mul`+* Bounds for containers: [0.3,0.6] -> [0.5.4,0.6.0.9]+* Add semiring instance for `Proxy` 0.1.2: [2018.05.04] -------------------
Data/Semiring.hs view
@@ -1,9 +1,15 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# OPTIONS_GHC -Wall #-}@@ -20,17 +26,21 @@ , foldMapP , foldMapT , sum- , prod+ , product , sum'- , prod'- + , product'++ -- * Types+ , Add(..)+ , Mul(..)+ -- * Ring typeclass , Ring(..) , (-) , minus ) where -import Control.Applicative (Alternative(..), Applicative(..), Const(..), liftA2)+import Control.Applicative (Applicative(..), Const(..), liftA2) import Data.Bool (Bool(..), (||), (&&), otherwise, not) import Data.Complex (Complex(..)) import Data.Eq (Eq(..))@@ -38,7 +48,7 @@ import Data.Foldable (Foldable) import qualified Data.Foldable as Foldable import Data.Function ((.), const, flip, id)-import Data.Functor (fmap)+import Data.Functor (Functor(..)) import Data.Functor.Identity (Identity(..)) #if defined(VERSION_unordered_containers) import Data.Hashable (Hashable)@@ -49,30 +59,35 @@ #endif import Data.Int (Int, Int8, Int16, Int32, Int64) import Data.Maybe (Maybe(..))+#if MIN_VERSION_base(4,12,0)+import Data.Monoid (Ap(..))+#endif #if defined(VERSION_containers)-import Data.IntMap (IntMap)-import qualified Data.IntMap as IntMap-import Data.IntSet (IntSet)-import qualified Data.IntSet as IntSet+--import Data.IntMap (IntMap)+--import qualified Data.IntMap as IntMap+--import Data.IntSet (IntSet)+--import qualified Data.IntSet as IntSet import Data.Map (Map) import qualified Data.Map as Map #endif-import Data.Monoid (Monoid(..),Dual(..), Endo(..), Product(..), Sum(..))-#if MIN_VERSION_base(4,8,0)-import Data.Monoid (Alt(..))-#endif+import Data.Monoid (Monoid(..),Dual(..), Product(..), Sum(..)) import Data.Ord (Ord(..), Ordering(..), compare) #if MIN_VERSION_base(4,6,0) import Data.Ord (Down(..)) #endif+import Data.Proxy (Proxy(..)) import Data.Ratio (Ratio)-import Data.Semigroup (Max(..), Min(..))+import Data.Semigroup (Semigroup(..),Max(..), Min(..)) #if defined(VERSION_containers)-import Data.Sequence (Seq)-import qualified Data.Sequence as Seq import Data.Set (Set) import qualified Data.Set as Set #endif+-- #if defined(VERSION_primitive)+-- import Data.Primitive.Array (Array(..))+-- import qualified Data.Primitive.Array as Array+-- #endif+import Data.Traversable (Traversable)+import Data.Typeable (Typeable) #if defined(VERSION_vector) import Data.Vector (Vector) import qualified Data.Vector as Vector@@ -88,12 +103,19 @@ CUIntMax, CUIntPtr, CULLong, CULong, CUSeconds, CUShort, CWchar) import Foreign.Ptr (IntPtr, WordPtr)+import Foreign.Storable (Storable) import GHC.Base (build)+import GHC.Enum (Enum, Bounded) import GHC.Float (Float, Double)+#if MIN_VERSION_base(4,6,1)+import GHC.Generics (Generic,Generic1)+#endif import GHC.IO (IO) import GHC.Integer (Integer) import qualified GHC.Num as Num-import GHC.Real (Integral, quot, even)+import GHC.Read (Read)+import GHC.Real (Integral, Fractional, Real, RealFrac, quot, even)+import GHC.Show (Show) import Numeric.Natural (Natural) import System.Posix.Types (CCc, CDev, CGid, CIno, CMode, CNlink,@@ -121,18 +143,22 @@ g x y z | even y = g (x * x) (y `quot` 2) z | y == 1 = x * z | otherwise = g (x * x) (y `quot` 2) (x * z)+{-# INLINE (^) #-} -- | Infix shorthand for 'plus'. (+) :: Semiring a => a -> a -> a (+) = plus+{-# INLINE (+) #-} -- | Infix shorthand for 'times'. (*) :: Semiring a => a -> a -> a (*) = times+{-# INLINE (*) #-} -- | Infix shorthand for 'minus'. (-) :: Ring a => a -> a -> a (-) = minus+{-# INLINE (-) #-} -- | Map each element of the structure to a semiring, and combine the results -- using 'plus'.@@ -150,22 +176,94 @@ -- This function is lazy. For a strict version, see 'sum''. sum :: (Foldable t, Semiring a) => t a -> a sum = Foldable.foldr plus zero+{-# INLINE sum #-} -- | The 'prod' function computes the multiplicative sum of the elements in a structure. -- This function is lazy. for a strict version, see 'prod''.-prod :: (Foldable t, Semiring a) => t a -> a-prod = Foldable.foldr times one+product :: (Foldable t, Semiring a) => t a -> a+product = Foldable.foldr times one+{-# INLINE product #-} -- | The 'sum'' function computes the additive sum of the elements in a structure. -- This function is strict. For a lazy version, see 'sum'. sum' :: (Foldable t, Semiring a) => t a -> a-sum' = Foldable.foldr' plus zero+sum' = Foldable.foldl' plus zero+{-# INLINE sum' #-} -- | The 'prod'' function computes the additive sum of the elements in a structure. -- This function is strict. For a lazy version, see 'prod'.-prod' :: (Foldable t, Semiring a) => t a -> a-prod' = Foldable.foldr' times one+product' :: (Foldable t, Semiring a) => t a -> a+product' = Foldable.foldl' times one+{-# INLINE product' #-} +newtype Add a = Add { getAdd :: a }+ deriving+ ( Bounded+ , Enum+ , Eq+ , Foldable+ , Fractional+ , Functor+#if MIN_VERSION_base(4,6,1)+ , Generic+ , Generic1+#endif+ , Num.Num+ , Ord+ , Read+ , Real+ , RealFrac+ , Semiring+ , Show+ , Storable+ , Traversable+ , Typeable+ )++newtype Mul a = Mul { getMul :: a }+ deriving+ ( Bounded+ , Enum+ , Eq+ , Foldable+ , Fractional+ , Functor+#if MIN_VERSION_base(4,6,1)+ , Generic+ , Generic1+#endif+ , Num.Num+ , Ord+ , Read+ , Real+ , RealFrac+ , Semiring+ , Show+ , Storable+ , Traversable+ , Typeable+ )++instance Semiring a => Semigroup (Add a) where+ (<>) = (+)+ {-# INLINE (<>) #-}++instance Semiring a => Monoid (Add a) where+ mempty = Add zero+ mappend = (<>)+ {-# INLINE mempty #-}+ {-# INLINE mappend #-}++instance Semiring a => Semigroup (Mul a) where+ (<>) = (*)+ {-# INLINE (<>) #-}++instance Semiring a => Monoid (Mul a) where+ mempty = Mul one+ mappend = (<>)+ {-# INLINE mempty #-}+ {-# INLINE mappend #-}+ {-------------------------------------------------------------------- Classes --------------------------------------------------------------------}@@ -175,8 +273,8 @@ -- can think of a semiring as two monoids of the same -- underlying type: A commutative monoid and an -- associative monoid. For any type R with a 'Prelude.Num'--- instance, the commutative monoid is (R, 'GHC.Num.+', 0)--- and the associative monoid is (R, 'GHC.Num.*', 1).+-- instance, the commutative monoid is (R, '(Prelude.+)', 0)+-- and the associative monoid is (R, '(Prelude.*)', 1). -- -- Instances should satisfy the following laws: --@@ -202,15 +300,12 @@ -- -- [/left- and right-distributivity of '*' over '+'/] ----- @--- x '*' (y '+' z) = (x '*' y) '+' (x '*' z)--- (x '+' y) '*' z = (x '*' z) '+' (y '*' z)--- @+-- @x '*' (y '+' z) = (x '*' y) '+' (x '*' z)@+-- @(x '+' y) '*' z = (x '*' z) '+' (y '*' z)@ -- -- [/annihilation/] -- -- @'zero' '*' x = x '*' 'zero' = 'zero'@--- class Semiring a where #if __GLASGOW_HASKELL__ >= 708@@ -222,10 +317,10 @@ one :: a -- ^ Associative Unit -- useful for defining semirings over ground types- default zero :: Num.Num a => a- default one :: Num.Num a => a- default plus :: Num.Num a => a -> a -> a- default times :: Num.Num a => a -> a -> a+ default zero :: Num.Num a => a -- ^ 0+ default one :: Num.Num a => a -- ^ 1+ default plus :: Num.Num a => a -> a -> a -- ^ '(Prelude.+)'+ default times :: Num.Num a => a -> a -> a -- ^ '(Prelude.*)' zero = 0 one = 1 plus = (Num.+)@@ -245,11 +340,12 @@ negate = Num.negate -- | Substract two 'Ring' values. For any type 'R' with--- a 'Prelude.Num' instance, this is the same as Prelude's 'GHC.Num.-'.+-- a 'Prelude.Num' instance, this is the same as '(Prelude.-)'. -- -- @x `minus` y = x '+' 'negate' y@ minus :: Ring a => a -> a -> a minus x y = x + negate y+{-# INLINE minus #-} {-------------------------------------------------------------------- Instances (base)@@ -260,27 +356,52 @@ zero = const zero times f g x = f x `times` g x one = const one+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring b => Ring (a -> b) where negate f x = negate (f x)+ {-# INLINE negate #-} instance Semiring () where plus _ _ = () zero = () times _ _ = () one = ()+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring () where negate _ = ()+ {-# INLINE negate #-} +instance Semiring (Proxy a) where+ plus _ _ = Proxy+ zero = Proxy+ times _ _ = Proxy+ one = Proxy+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-}+ instance Semiring Bool where plus = (||) zero = False times = (&&) one = True+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring Bool where negate = not+ {-# INLINE negate #-} -- See Section: List fusion instance Semiring a => Semiring [a] where@@ -288,9 +409,14 @@ one = [one] plus = listAdd times = listTimes+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring a => Ring [a] where negate = fmap negate+ {-# INLINE negate #-} instance Semiring a => Semiring (Maybe a) where zero = Nothing@@ -303,75 +429,85 @@ times Nothing _ = Nothing times _ Nothing = Nothing times (Just x) (Just y) = Just (times x y)+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring a => Ring (Maybe a) where negate = fmap negate+ {-# INLINE negate #-} instance Semiring a => Semiring (IO a) where zero = pure zero one = pure one plus = liftA2 plus times = liftA2 times+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring a => Ring (IO a) where negate = fmap negate+ {-# INLINE negate #-} instance Semiring a => Semiring (Dual a) where zero = Dual zero Dual x `plus` Dual y = Dual (y `plus` x) one = Dual one Dual x `times` Dual y = Dual (y `times` x)+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring a => Ring (Dual a) where negate (Dual x) = Dual (negate x)---- | This is not a true semiring. Even if the underlying--- monoid is commutative, it is only a near semiring. It--- is, however, quite useful. For instance, this type:------ @forall a. 'Endo' ('Endo' a)@------ is a valid encoding of church numerals, with addition and--- multiplication being their semiring variants.-instance Monoid a => Semiring (Endo a) where- zero = Endo mempty- plus (Endo f) (Endo g) = Endo (mappend f g)- one = mempty- times = mappend--instance (Monoid a, Ring a) => Ring (Endo a) where- negate (Endo f) = Endo (negate f)--#if MIN_VERSION_base(4,8,0)-instance (Alternative f, Semiring a) => Semiring (Alt f a) where- zero = empty- one = Alt (pure one)- plus = (<|>)- times = liftA2 times--instance (Alternative f, Ring a) => Ring (Alt f a) where- negate = fmap negate-#endif+ {-# INLINE negate #-} instance Semiring a => Semiring (Const a b) where zero = Const zero one = Const one plus (Const x) (Const y) = Const (x `plus` y) times (Const x) (Const y) = Const (x `times` y)+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring a => Ring (Const a b) where negate (Const x) = Const (negate x)+ {-# INLINE negate #-} +-- | This instance can suffer due to floating point arithmetic. instance Ring a => Semiring (Complex a) where zero = zero :+ zero one = one :+ zero plus (x :+ y) (x' :+ y') = plus x x' :+ plus y y' times (x :+ y) (x' :+ y') = (x * x' - (y * y')) :+ (x * y' + y * x')+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring a => Ring (Complex a) where negate (x :+ y) = negate x :+ negate y+ {-# INLINE negate #-} +#if MIN_VERSION_base(4,12,0)+instance (Semiring a, Applicative f) => Semiring (Ap f a) where+ zero = pure zero+ one = pure one+ plus = liftA2 plus+ times = liftA2 times+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-}+#endif+ instance Semiring Int instance Semiring Int8 instance Semiring Int16@@ -383,7 +519,9 @@ instance Semiring Word16 instance Semiring Word32 instance Semiring Word64+-- | This instance can suffer due to floating point arithmetic. instance Semiring Float+-- | This instance can suffer due to floating point arithmetic. instance Semiring Double instance Semiring CUIntMax instance Semiring CIntMax@@ -427,6 +565,7 @@ instance Semiring CIno instance Semiring CDev instance Semiring Natural+-- | Non-negative rational numbers form a semiring. instance Integral a => Semiring (Ratio a) deriving instance Semiring a => Semiring (Product a) deriving instance Semiring a => Semiring (Sum a)@@ -509,50 +648,71 @@ --------------------------------------------------------------------} #if defined(VERSION_containers)-instance (Ord a, Semiring a) => Semiring (Set a) where++-- | The multiplication laws are satisfied for+-- any underlying 'Monoid', so we require a+-- 'Monoid' contraint instead of a 'Semiring'+-- constraint since 'times' can use+-- the context of either.+instance (Ord a, Monoid a) => Semiring (Set a) where zero = Set.empty- one = Set.singleton one+ one = Set.singleton mempty plus = Set.union-#if MIN_VERSION_containers(5,11,0)- times xs ys = Set.map (P.uncurry times) (Set.cartesianProduct xs ys)-#else- -- I think this could also be 'times xs ys = foldMapT (flip Set.map ys . times) xs'- times xs ys = Set.fromList (times (Set.toList xs) (Set.toList ys))-#endif+ times xs ys = Foldable.foldMap (flip Set.map ys . mappend) xs+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} -instance (Ord a, Semiring a, Semiring b) => Semiring (Map a b) where+-- | The multiplication laws are satisfied for+-- any underlying 'Monoid' as the key type,+-- so we require a 'Monoid' contraint instead of+-- a 'Semiring' constraint since 'times' can use+-- the context of either.+instance (Ord k, Monoid k, Semiring v) => Semiring (Map k v) where zero = Map.empty- one = Map.singleton zero one+ one = Map.singleton mempty one plus = Map.unionWith (+) xs `times` ys = Map.fromListWith (+)- [ (plus k l, v * u)+ [ (mappend k l, v * u) | (k,v) <- Map.toList xs , (l,u) <- Map.toList ys ]--instance Semiring IntSet where- zero = IntSet.empty- one = IntSet.singleton one- plus = IntSet.union- times xs ys = IntSet.fromList (times (IntSet.toList xs) (IntSet.toList ys))+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} -instance (Semiring a) => Semiring (IntMap a) where- zero = IntMap.empty- one = IntMap.singleton zero one- plus = IntMap.unionWith (+)- xs `times` ys- = IntMap.fromListWith (+)- [ (plus k l, v * u)- | (k,v) <- IntMap.toList xs- , (l,u) <- IntMap.toList ys- ]+--newtype IntSetP = IntSetP { intSetP :: IntSet }+--newtype IntSetT = IntSetT { intSetT :: IntSet }+--+--instance Semiring IntSetP where+-- zero = IntSetP (IntSet.empty)+-- one = IntSetP (IntSet.singleton zero)+-- plus (IntSetP x) (IntSetP y) = IntSetP (IntSet.union x y)+-- times (IntSetP xs) (IntSetP ys) = IntSetP (foldMapIntSet (flip IntSet.map ys . plus) xs)+--+--instance Semiring IntSetT where+-- zero = IntSetT IntSet.empty+-- one = IntSetT (IntSet.singleton one)+-- plus (IntSetT x) (IntSetT y) = IntSetT (IntSet.union x y)+-- times (IntSetT xs) (IntSetT ys) = IntSetT (foldMapIntSet (flip IntSet.map ys . times) xs)+--+--foldMapIntSet :: Monoid m => (Int -> m) -> IntSet -> m+--foldMapIntSet f = IntSet.foldl' (flip (mappend . f)) mempty+--{-# INLINE foldMapIntSet #-} -instance (Semiring a) => Semiring (Seq a) where- zero = Seq.empty- one = Seq.singleton one- plus = (Seq.><)- times xs ys = Seq.fromList (times (Foldable.toList xs) (Foldable.toList ys))+--instance (Semiring a) => Semiring (IntMap a) where+-- zero = IntMap.empty+-- one = IntMap.singleton zero one+-- plus = IntMap.unionWith (+)+-- xs `times` ys+-- = IntMap.fromListWith (+)+-- [ (plus k l, v * u)+-- | (k,v) <- IntMap.toList xs+-- , (l,u) <- IntMap.toList ys+-- ] #endif {--------------------------------------------------------------------@@ -560,24 +720,67 @@ --------------------------------------------------------------------} #if defined(VERSION_unordered_containers)-instance (Eq a, Hashable a, Semiring a) => Semiring (HashSet a) where++-- | The multiplication laws are satisfied for+-- any underlying 'Monoid', so we require a+-- 'Monoid' contraint instead of a 'Semiring'+-- constraint since 'times' can use+-- the context of either.+instance (Eq a, Hashable a, Monoid a) => Semiring (HashSet a) where zero = HashSet.empty- one = HashSet.singleton one+ one = HashSet.singleton mempty plus = HashSet.union- times xs ys = foldMapT (flip HashSet.map ys . times) xs+ times xs ys = Foldable.foldMap (flip HashSet.map ys . mappend) xs+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} -instance (Eq k, Hashable k, Semiring k, Semiring v) => Semiring (HashMap k v) where+-- | The multiplication laws are satisfied for+-- any underlying 'Monoid' as the key type,+-- so we require a 'Monoid' contraint instead of+-- a 'Semiring' constraint since 'times' can use+-- the context of either.+instance (Eq k, Hashable k, Monoid k, Semiring v) => Semiring (HashMap k v) where zero = HashMap.empty- one = HashMap.singleton zero one+ one = HashMap.singleton mempty one plus = HashMap.unionWith (+) xs `times` ys = HashMap.fromListWith (+)- [ (k + l, v * u)+ [ (mappend k l, v * u) | (k,v) <- HashMap.toList xs- , (l,u) <- HashMap.toList ys ]+ , (l,u) <- HashMap.toList ys+ ]+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} #endif {--------------------------------------------------------------------+ Instances (primitive)+--------------------------------------------------------------------}++#if defined(VERSION_primitive)+-- | The multiplication laws are satisfied for+-- any underlying 'Monoid', so we require a+-- 'Monoid' contraint instead of a 'Semiring'+-- constraint since 'times' can use+-- the context of either.+-- instance (Monoid a) => Semiring (Array a) where+-- zero = mempty+-- one = runST e where+-- e :: forall s. Monoid a => ST s (Array a)+-- e = (Array.newArray 1 mempty) >>= Array.unsafeFreezeArray+-- plus _ _ = mempty+-- times _ _ = mempty+-- {-# INLINE plus #-}+-- {-# INLINE zero #-}+-- {-# INLINE times #-}+-- {-# INLINE one #-}+#endif++{-------------------------------------------------------------------- Instances (vector) --------------------------------------------------------------------} @@ -590,24 +793,31 @@ EQ -> Vector.zipWith (+) xs ys LT -> Vector.unsafeAccumulate (+) ys (Vector.indexed xs) GT -> Vector.unsafeAccumulate (+) xs (Vector.indexed ys)- times xs ys- | Vector.null xs = Vector.empty- | Vector.null ys = Vector.empty- | otherwise = Vector.generate maxlen f- where- f n = Foldable.foldl'- (\_ k -> - Vector.unsafeIndex xs k *- Vector.unsafeIndex ys (n Num.- k)) zero [kmin .. kmax]- where- !kmin = max 0 (n Num.- (klen Num.- 1))- !kmax = min n (slen Num.- 1)- !slen = Vector.length xs- !klen = Vector.length ys- !maxlen = max slen klen+ times signal kernel+ | Vector.null signal = Vector.empty+ | Vector.null kernel = Vector.empty+ | otherwise = Vector.generate (slen + klen - 1) f+ where+ !slen = Vector.length signal+ !klen = Vector.length kernel+ f n = Foldable.foldl'+ (\a k -> a ++ Vector.unsafeIndex signal k *+ Vector.unsafeIndex kernel (n - k)+ )+ zero+ [kmin .. kmax]+ where+ !kmin = max 0 (n - (klen - 1))+ !kmax = min n (slen - 1)+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-} instance Ring a => Ring (Vector a) where negate = Vector.map negate+ {-# INLINE negate #-} instance (UV.Unbox a, Semiring a) => Semiring (UV.Vector a) where zero = UV.empty@@ -617,28 +827,35 @@ EQ -> UV.zipWith (+) xs ys LT -> UV.unsafeAccumulate (+) ys (UV.indexed xs) GT -> UV.unsafeAccumulate (+) xs (UV.indexed ys)- times xs ys- | UV.null xs = UV.empty- | UV.null ys = UV.empty- | otherwise = UV.generate maxlen f- where- f n = Foldable.foldl'- (\_ k -> - UV.unsafeIndex xs k *- UV.unsafeIndex ys (n Num.- k)) zero [kmin .. kmax]- where- !kmin = max 0 (n Num.- (klen Num.- 1))- !kmax = min n (slen Num.- 1)- !slen = UV.length xs- !klen = UV.length ys- !maxlen = max slen klen-+ times signal kernel+ | UV.null signal = UV.empty+ | UV.null kernel = UV.empty+ | otherwise = UV.generate (slen + klen - 1) f+ where+ !slen = UV.length signal+ !klen = UV.length kernel+ f n = Foldable.foldl'+ (\a k -> a ++ UV.unsafeIndex signal k *+ UV.unsafeIndex kernel (n - k)+ )+ zero+ [kmin .. kmax]+ where+ !kmin = max 0 (n - (klen - 1))+ !kmax = min n (slen - 1)+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-}+ instance (UV.Unbox a, Ring a) => Ring (UV.Vector a) where negate = UV.map negate+ {-# INLINE negate #-} instance (SV.Storable a, Semiring a) => Semiring (SV.Vector a) where zero = SV.empty- one = SV.singleton one+ one = SV.singleton one plus xs ys = case compare lxs lys of EQ -> SV.zipWith (+) xs ys@@ -647,24 +864,30 @@ where lxs = SV.length xs lys = SV.length ys- times xs ys- | SV.null xs = SV.empty- | SV.null ys = SV.empty- | otherwise = SV.generate maxlen f+ times signal kernel+ | SV.null signal = SV.empty+ | SV.null kernel = SV.empty+ | otherwise = SV.generate (slen + klen - 1) f where+ !slen = SV.length signal+ !klen = SV.length kernel f n = Foldable.foldl'- (\_ k -> - SV.unsafeIndex xs k *- SV.unsafeIndex ys (n Num.- k)) zero [kmin .. kmax]+ (\a k -> a ++ SV.unsafeIndex signal k *+ SV.unsafeIndex kernel (n - k))+ zero+ [kmin .. kmax] where- !kmin = max 0 (n Num.- (klen Num.- 1))- !kmax = min n (slen Num.- 1)- !slen = SV.length xs- !klen = SV.length ys- !maxlen = max slen klen-+ !kmin = max 0 (n - (klen - 1))+ !kmax = min n (slen - 1)+ {-# INLINE plus #-}+ {-# INLINE zero #-}+ {-# INLINE times #-}+ {-# INLINE one #-}+ instance (SV.Storable a, Ring a) => Ring (SV.Vector a) where negate = SV.map negate+ {-# INLINE negate #-} #endif -- [Section: List fusion]
+ Data/Semiring/Free.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE StandaloneDeriving #-}++#if !MIN_VERSION_base(4,9,0)+{-# OPTIONS_GHC -fno-warn-orphans #-}+#endif++module Data.Semiring.Free+ (+#if defined(VERSION_containers)+#if MIN_VERSION_base(4,8,0)+ Free(..)+ , runFree+ , lowerFree+ , liftFree+#endif+#endif+ ) where++#if defined(VERSION_containers)+#if MIN_VERSION_base(4,8,0)+import Control.Applicative (pure)+import Data.Bool (otherwise)+import Data.Coerce (Coercible, coerce)+import Data.Eq (Eq)+import Data.Functor (Functor(..))+import Data.Functor.Identity (Identity(..))+import Data.Function (flip,id, (.))+import Data.Ord (Ord)+#if !MIN_VERSION_base(4,9,0)+import Data.Semigroup ()+#endif+import Data.Semiring+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import Data.Monoid (Monoid(..))++import GHC.Show (Show)+import GHC.Read (Read)+import GHC.Real (even, div)+import Numeric.Natural++newtype Free a = Free+ { getFree :: Map (Identity a) Natural+ } deriving (Show, Read, Eq, Ord, Semiring)++#if !MIN_VERSION_base(4,9,0)+--deriving instance Semigroup a => Semigroup (Identity a)+deriving instance Monoid a => Monoid (Identity a)+#endif++runFree :: Semiring s => (a -> s) -> Free a -> s+runFree f = getAdd #. Map.foldMapWithKey ((rep .# Add) . product . fmap f) . getFree++lowerFree :: Semiring s => Free s -> s+lowerFree = runFree id++liftFree :: a -> Free a+liftFree = Free . flip Map.singleton one . pure++rep :: Monoid m => m -> Natural -> m+rep x = go+ where+ go 0 = mempty+ go 1 = x+ go n+ | even n = r `mappend` r+ | otherwise = x `mappend` r `mappend` r+ where+ r = go (n `div` 2)+{-# INLINE rep #-}++-- | Coercive left-composition.+infixr 9 #.+(#.) :: Coercible b c => (b -> c) -> (a -> b) -> a -> c+(#.) _ = coerce+{-# INLINE (#.) #-}++-- | Coercive right-composition.+infixr 9 .#+(.#) :: Coercible a b => (b -> c) -> (a -> b) -> a -> c+(.#) f _ = coerce f+{-# INLINE (.#) #-}++#endif++#endif
Data/Semiring/Generic.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE CPP #-}+#if MIN_VERSION_base(4,6,0) {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeOperators #-}-+#endif {-# OPTIONS_GHC -Wall #-} -- below are safe orphan instances
Data/Star.hs view
@@ -1,17 +1,14 @@+{-# LANGUAGE NoImplicitPrelude #-}+ module Data.Star ( Star(..) ) where -import Control.Monad (ap)-import Control.Monad.Fix (fix) import Data.Bool (Bool(..)) import Data.Function (id, (.))-import Data.Monoid-+import Data.Proxy (Proxy(..)) import Data.Semiring -import Prelude hiding (Num(..))- -- | A <https://en.wikipedia.org/wiki/Semiring#Star_semirings Star semiring> -- adds one operation, 'star' to a 'Semiring', such that it follows the -- law:@@ -32,22 +29,24 @@ instance Star b => Star (a -> b) where star = (.) star aplus = (.) aplus+ {-# INLINE star #-}+ {-# INLINE aplus #-} instance Star Bool where star _ = True aplus = id+ {-# INLINE star #-}+ {-# INLINE aplus #-} instance Star () where star _ = () aplus _ = ()+ {-# INLINE star #-}+ {-# INLINE aplus #-} -instance (Eq a, Monoid a) => Star (Endo a) where- star (Endo f) = Endo converge- where- if' :: Bool -> a -> a -> a- if' True x _ = x- if' False _ y = y- converge = fix (ap mappend . ap (if' =<< ap (==) (ap mappend f)) . (. ap mappend f))- --converge inp = mappend inp (if inp == next then inp else converge next)- -- where- -- next = mappend inp (f inp)+instance Star (Proxy a) where+ star _ = Proxy+ aplus _ = Proxy+ {-# INLINE star #-}+ {-# INLINE aplus #-}+
README.md view
@@ -5,7 +5,7 @@ A Semiring has two appending operations, 'plus' and 'times', and two respective identity elements, 'zero' and 'one'. -More formally, A semiring <i>R</i> is a set equipped with two binary relations + and *, such that:+More formally, A semiring R is a set equipped with two binary relations + and *, such that: - (R, +) is a commutative monoid with identity element 0: - (a + b) + c = a + (b + c)@@ -45,9 +45,11 @@ Some relevant (informal) reading material: -http://stedolan.net/research/semirings.pdf <br>-http://r6.ca/blog/20110808T035622Z.html <br>-https://byorgey.wordpress.com/2016/04/05/the-network-reliability-problem-and-star-semirings/ <br>+http://stedolan.net/research/semirings.pdf++http://r6.ca/blog/20110808T035622Z.html++https://byorgey.wordpress.com/2016/04/05/the-network-reliability-problem-and-star-semirings/ additional credit ======
semirings.cabal view
@@ -1,6 +1,6 @@ name: semirings category: Algebra, Data, Data Structures, Math, Maths, Mathematics-version: 0.1.3.0+version: 0.2.0.0 license: BSD3 cabal-version: >= 1.10 license-file: LICENSE@@ -13,7 +13,6 @@ synopsis: two monoids as one, in holy haskimony description: In mathematics, a semiring is an algebraic structure consisting of a set together with two binary operations, one commutative and one associative. A semiring has two identity elements respective to its operations. Thus a semiring can be seen as a combination of two monoids, a commutative monoid and an associative monoid.- For some useful semirings, see the 'semirings-types' package. build-type: Simple extra-source-files: README.md CHANGELOG.md tested-with: GHC == 7.4.1 @@ -32,6 +31,8 @@ , GHC == 8.2.2 , GHC == 8.4.1 , GHC == 8.4.2+ , GHC == 8.4.3+ , GHC == 8.6.1 source-repository head type: git@@ -43,8 +44,6 @@ . Disabling this may be useful for accelerating builds in sandboxes for expert users. .- If disabled we will not supply instances of `Hashable`- . Note: `-f-hashable` implies `-f-unordered-containers`, as we are necessarily not able to supply those instances as well. default: True manual: True@@ -88,17 +87,21 @@ if impl(ghc < 8.0) build-depends: semigroups- ++ if impl(ghc < 7.8)+ build-depends: tagged+ if impl(ghc >= 7.2) exposed-modules: Data.Semiring+ Data.Semiring.Free Data.Star if impl(ghc >= 7.6.1) exposed-modules: Data.Semiring.Generic- + if flag(containers)- build-depends: containers >= 0.3 && < 0.6+ build-depends: containers >= 0.5.4 && < 0.6.1.0 if flag(hashable) build-depends: hashable >= 1.1 && < 1.3