packages feed

semiring-num 0.6.0.0 → 0.7.0.0

raw patch · 7 files changed

+1013/−468 lines, 7 filesdep +QuickCheckdep +nat-sized-numbersdep +template-haskellPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, nat-sized-numbers, template-haskell

API changes (from Hackage documentation)

- Data.Semiring: instance (Data.Semiring.Semiring a, Data.Semiring.Semiring b) => Data.Semiring.Semiring (a, b)
- Data.Semiring: instance (Data.Semiring.Semiring a, Data.Semiring.Semiring b, Data.Semiring.Semiring c) => Data.Semiring.Semiring (a, b, c)
- Data.Semiring: instance (Data.Semiring.Semiring a, Data.Semiring.Semiring b, Data.Semiring.Semiring c, Data.Semiring.Semiring d) => Data.Semiring.Semiring (a, b, c, d)
- Data.Semiring: instance (Data.Semiring.Semiring a, Data.Semiring.Semiring b, Data.Semiring.Semiring c, Data.Semiring.Semiring d, Data.Semiring.Semiring e) => Data.Semiring.Semiring (a, b, c, d, e)
- Data.Semiring: instance (Data.Semiring.Semiring a, GHC.Classes.Ord a) => Data.Semiring.Semiring (Data.Semiring.Max a)
- Data.Semiring: instance (Data.Semiring.Semiring a, GHC.Classes.Ord a) => Data.Semiring.Semiring (Data.Semiring.Min a)
- Data.Semiring: instance (GHC.Classes.Ord a, GHC.Base.Monoid a) => Data.Semiring.Semiring (Data.Set.Base.Set a)
- Data.Semiring: instance GHC.Base.Applicative Data.Semiring.Add
- Data.Semiring: instance GHC.Base.Applicative Data.Semiring.Max
- Data.Semiring: instance GHC.Base.Applicative Data.Semiring.Min
- Data.Semiring: instance GHC.Base.Applicative Data.Semiring.Mul
- Data.Semiring: instance GHC.Base.Monad Data.Semiring.Add
- Data.Semiring: instance GHC.Base.Monad Data.Semiring.Max
- Data.Semiring: instance GHC.Base.Monad Data.Semiring.Min
- Data.Semiring: instance GHC.Base.Monad Data.Semiring.Mul
- Data.Semiring: instance GHC.Classes.Ord a => GHC.Base.Monoid (Data.Semiring.Max a)
- Data.Semiring: instance GHC.Classes.Ord a => GHC.Base.Monoid (Data.Semiring.Min a)
- Data.Semiring.Numeric: instance (Data.Semiring.Semiring a, GHC.Float.Floating a) => Data.Semiring.Semiring (Data.Semiring.Numeric.Log a)
- Data.Semiring.Numeric: instance GHC.Base.Applicative Data.Semiring.Numeric.Bottleneck
- Data.Semiring.Numeric: instance GHC.Base.Applicative Data.Semiring.Numeric.Division
- Data.Semiring.Numeric: instance GHC.Base.Applicative Data.Semiring.Numeric.Log
- Data.Semiring.Numeric: instance GHC.Base.Applicative Data.Semiring.Numeric.Viterbi
- Data.Semiring.Numeric: instance GHC.Base.Applicative Data.Semiring.Numeric.Łukasiewicz
- Data.Semiring.Numeric: instance GHC.Base.Monad Data.Semiring.Numeric.Bottleneck
- Data.Semiring.Numeric: instance GHC.Base.Monad Data.Semiring.Numeric.Division
- Data.Semiring.Numeric: instance GHC.Base.Monad Data.Semiring.Numeric.Log
- Data.Semiring.Numeric: instance GHC.Base.Monad Data.Semiring.Numeric.Viterbi
- Data.Semiring.Numeric: instance GHC.Base.Monad Data.Semiring.Numeric.Łukasiewicz
+ Data.Semiring: Finite :: !a -> Infinite a
+ Data.Semiring: NegFinite :: !a -> NegativeInfinite a
+ Data.Semiring: Negative :: Infinite a
+ Data.Semiring: NegativeInfinity :: NegativeInfinite a
+ Data.Semiring: PosFinite :: !a -> PositiveInfinite a
+ Data.Semiring: Positive :: Infinite a
+ Data.Semiring: PositiveInfinity :: PositiveInfinite a
+ Data.Semiring: class HasNegativeInfinity a where negativeInfinity = negate (1 / 0)
+ Data.Semiring: class HasPositiveInfinity a where positiveInfinity = 1 / 0
+ Data.Semiring: class Semiring a => StarSemiring a where star x = one <+> plus x plus x = x <.> star x
+ Data.Semiring: data Infinite a
+ Data.Semiring: data NegativeInfinite a
+ Data.Semiring: data PositiveInfinite a
+ Data.Semiring: instance (Data.Semiring.Semiring a, GHC.Classes.Ord a, Data.Semiring.Infinite.HasNegativeInfinity a) => Data.Semiring.Semiring (Data.Semiring.Max a)
+ Data.Semiring: instance (Data.Semiring.Semiring a, GHC.Classes.Ord a, Data.Semiring.Infinite.HasPositiveInfinity a) => Data.Semiring.Semiring (Data.Semiring.Min a)
+ Data.Semiring: instance (Data.Semiring.Semiring a, GHC.Classes.Ord a, Data.Semiring.Infinite.HasPositiveInfinity a, Data.Semiring.Infinite.HasNegativeInfinity a) => Data.Semiring.StarSemiring (Data.Semiring.Max a)
+ Data.Semiring: instance (Data.Semiring.Semiring a, GHC.Classes.Ord a, Data.Semiring.Infinite.HasPositiveInfinity a, Data.Semiring.Infinite.HasNegativeInfinity a) => Data.Semiring.StarSemiring (Data.Semiring.Min a)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1) => Data.Semiring.Semiring (a0, a1)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1, Data.Semiring.Semiring a2) => Data.Semiring.Semiring (a0, a1, a2)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1, Data.Semiring.Semiring a2, Data.Semiring.Semiring a3) => Data.Semiring.Semiring (a0, a1, a2, a3)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1, Data.Semiring.Semiring a2, Data.Semiring.Semiring a3, Data.Semiring.Semiring a4) => Data.Semiring.Semiring (a0, a1, a2, a3, a4)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1, Data.Semiring.Semiring a2, Data.Semiring.Semiring a3, Data.Semiring.Semiring a4, Data.Semiring.Semiring a5) => Data.Semiring.Semiring (a0, a1, a2, a3, a4, a5)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1, Data.Semiring.Semiring a2, Data.Semiring.Semiring a3, Data.Semiring.Semiring a4, Data.Semiring.Semiring a5, Data.Semiring.Semiring a6) => Data.Semiring.Semiring (a0, a1, a2, a3, a4, a5, a6)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1, Data.Semiring.Semiring a2, Data.Semiring.Semiring a3, Data.Semiring.Semiring a4, Data.Semiring.Semiring a5, Data.Semiring.Semiring a6, Data.Semiring.Semiring a7) => Data.Semiring.Semiring (a0, a1, a2, a3, a4, a5, a6, a7)
+ Data.Semiring: instance (Data.Semiring.Semiring a0, Data.Semiring.Semiring a1, Data.Semiring.Semiring a2, Data.Semiring.Semiring a3, Data.Semiring.Semiring a4, Data.Semiring.Semiring a5, Data.Semiring.Semiring a6, Data.Semiring.Semiring a7, Data.Semiring.Semiring a8) => Data.Semiring.Semiring (a0, a1, a2, a3, a4, a5, a6, a7, a8)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1) => Data.Semiring.StarSemiring (a0, a1)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1, Data.Semiring.StarSemiring a2) => Data.Semiring.StarSemiring (a0, a1, a2)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1, Data.Semiring.StarSemiring a2, Data.Semiring.StarSemiring a3) => Data.Semiring.StarSemiring (a0, a1, a2, a3)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1, Data.Semiring.StarSemiring a2, Data.Semiring.StarSemiring a3, Data.Semiring.StarSemiring a4) => Data.Semiring.StarSemiring (a0, a1, a2, a3, a4)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1, Data.Semiring.StarSemiring a2, Data.Semiring.StarSemiring a3, Data.Semiring.StarSemiring a4, Data.Semiring.StarSemiring a5) => Data.Semiring.StarSemiring (a0, a1, a2, a3, a4, a5)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1, Data.Semiring.StarSemiring a2, Data.Semiring.StarSemiring a3, Data.Semiring.StarSemiring a4, Data.Semiring.StarSemiring a5, Data.Semiring.StarSemiring a6) => Data.Semiring.StarSemiring (a0, a1, a2, a3, a4, a5, a6)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1, Data.Semiring.StarSemiring a2, Data.Semiring.StarSemiring a3, Data.Semiring.StarSemiring a4, Data.Semiring.StarSemiring a5, Data.Semiring.StarSemiring a6, Data.Semiring.StarSemiring a7) => Data.Semiring.StarSemiring (a0, a1, a2, a3, a4, a5, a6, a7)
+ Data.Semiring: instance (Data.Semiring.StarSemiring a0, Data.Semiring.StarSemiring a1, Data.Semiring.StarSemiring a2, Data.Semiring.StarSemiring a3, Data.Semiring.StarSemiring a4, Data.Semiring.StarSemiring a5, Data.Semiring.StarSemiring a6, Data.Semiring.StarSemiring a7, Data.Semiring.StarSemiring a8) => Data.Semiring.StarSemiring (a0, a1, a2, a3, a4, a5, a6, a7, a8)
+ Data.Semiring: instance (GHC.Base.Monoid a, GHC.Classes.Eq a) => Data.Semiring.StarSemiring (Data.Monoid.Endo a)
+ Data.Semiring: instance (GHC.Classes.Eq a, Data.Semiring.Semiring a) => Data.Semiring.StarSemiring (Data.Semiring.Infinite.PositiveInfinite a)
+ Data.Semiring: instance (GHC.Classes.Ord a, Data.Semiring.Infinite.HasNegativeInfinity a) => GHC.Base.Monoid (Data.Semiring.Max a)
+ Data.Semiring: instance (GHC.Classes.Ord a, Data.Semiring.Infinite.HasPositiveInfinity a) => GHC.Base.Monoid (Data.Semiring.Min a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semiring.Infinite.Infinite a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semiring.Infinite.NegativeInfinite a)
+ Data.Semiring: instance Data.Semiring.Semiring a => Data.Semiring.Semiring (Data.Semiring.Infinite.PositiveInfinite a)
+ Data.Semiring: instance Data.Semiring.StarSemiring ()
+ Data.Semiring: instance Data.Semiring.StarSemiring Data.Monoid.All
+ Data.Semiring: instance Data.Semiring.StarSemiring Data.Monoid.Any
+ Data.Semiring: instance Data.Semiring.StarSemiring GHC.Types.Bool
+ Data.Semiring: instance Data.Semiring.StarSemiring a => Data.Semiring.StarSemiring (Data.Semiring.Add a)
+ Data.Semiring: instance Data.Semiring.StarSemiring a => Data.Semiring.StarSemiring (Data.Semiring.Mul a)
+ Data.Semiring: instance Data.Semiring.StarSemiring b => Data.Semiring.StarSemiring (a -> b)
+ Data.Semiring: instance Data.Traversable.Traversable Data.Semiring.Add
+ Data.Semiring: instance Data.Traversable.Traversable Data.Semiring.Max
+ Data.Semiring: instance Data.Traversable.Traversable Data.Semiring.Min
+ Data.Semiring: instance Data.Traversable.Traversable Data.Semiring.Mul
+ Data.Semiring: instance Foreign.Storable.Storable a => Foreign.Storable.Storable (Data.Semiring.Max a)
+ Data.Semiring: instance Foreign.Storable.Storable a => Foreign.Storable.Storable (Data.Semiring.Min a)
+ Data.Semiring: instance GHC.Enum.Enum a => GHC.Enum.Enum (Data.Semiring.Max a)
+ Data.Semiring: instance GHC.Enum.Enum a => GHC.Enum.Enum (Data.Semiring.Min a)
+ Data.Semiring: instance GHC.Num.Num a => GHC.Num.Num (Data.Semiring.Max a)
+ Data.Semiring: instance GHC.Num.Num a => GHC.Num.Num (Data.Semiring.Min a)
+ Data.Semiring: instance GHC.Real.Fractional a => GHC.Real.Fractional (Data.Semiring.Max a)
+ Data.Semiring: instance GHC.Real.Fractional a => GHC.Real.Fractional (Data.Semiring.Min a)
+ Data.Semiring: instance GHC.Real.Real a => GHC.Real.Real (Data.Semiring.Max a)
+ Data.Semiring: instance GHC.Real.Real a => GHC.Real.Real (Data.Semiring.Min a)
+ Data.Semiring: instance GHC.Real.RealFrac a => GHC.Real.RealFrac (Data.Semiring.Max a)
+ Data.Semiring: instance GHC.Real.RealFrac a => GHC.Real.RealFrac (Data.Semiring.Min a)
+ Data.Semiring: negativeInfinity :: (HasNegativeInfinity a, RealFloat a) => a
+ Data.Semiring: plus :: StarSemiring a => a -> a
+ Data.Semiring: positiveInfinity :: (HasPositiveInfinity a, RealFloat a) => a
+ Data.Semiring: star :: StarSemiring a => a -> a
+ Data.Semiring.Numeric: instance (GHC.Float.Floating a, Data.Semiring.Infinite.HasPositiveInfinity a) => Data.Semiring.Semiring (Data.Semiring.Numeric.Log a)
+ Data.Semiring.Numeric: instance Data.Traversable.Traversable Data.Semiring.Numeric.Bottleneck
+ Data.Semiring.Numeric: instance Data.Traversable.Traversable Data.Semiring.Numeric.Division
+ Data.Semiring.Numeric: instance Data.Traversable.Traversable Data.Semiring.Numeric.Viterbi
+ Data.Semiring.Numeric: instance Data.Traversable.Traversable Data.Semiring.Numeric.Łukasiewicz
+ Test.Semiring: nearTernaryLaws :: (Eq a, Semiring a, Show a) => a -> a -> a -> Either String String
+ Test.Semiring: nearUnLaws :: (Eq a, Semiring a, Show a) => a -> Either String String
+ Test.Semiring: ordLaws :: (Ord a, Semiring a, Show a) => a -> a -> a -> Either String String
+ Test.Semiring: plusLaw :: (Eq a, StarSemiring a, Show a) => a -> Either String String
+ Test.Semiring: starLaw :: (Eq a, StarSemiring a, Show a) => a -> Either String String
+ Test.Semiring: starLaws :: (Eq a, StarSemiring a, Show a) => a -> Either String String
- Data.Semiring: Max :: Maybe a -> Max a
+ Data.Semiring: Max :: a -> Max a
- Data.Semiring: Min :: Maybe a -> Min a
+ Data.Semiring: Min :: a -> Min a
- Data.Semiring: [getMax] :: Max a -> Maybe a
+ Data.Semiring: [getMax] :: Max a -> a
- Data.Semiring: [getMin] :: Min a -> Maybe a
+ Data.Semiring: [getMin] :: Min a -> a
- Data.Semiring.Numeric: Log :: Maybe a -> Log a
+ Data.Semiring.Numeric: Log :: a -> Log a
- Data.Semiring.Numeric: [getLog] :: Log a -> Maybe a
+ Data.Semiring.Numeric: [getLog] :: Log a -> a

Files

semiring-num.cabal view
@@ -1,5 +1,5 @@ name:                semiring-num-version:             0.6.0.0+version:             0.7.0.0 synopsis:            Basic semiring class and instances description:         Adds a basic semiring class homepage:            https://github.com/oisdk/semiring-num@@ -18,8 +18,11 @@                      , Data.Semiring.Numeric                      , Data.Semiring.Free                      , Test.Semiring+  other-modules:       Data.Semiring.Infinite+                     , Data.Semiring.TH   build-depends:       base >= 4.9 && < 5                      , containers >= 0.5+                     , template-haskell >= 2.11   default-language:    Haskell2010   ghc-options:         -Wall @@ -32,6 +35,8 @@                      , smallcheck >= 1.1                      , doctest >= 0.11                      , containers >= 0.5+                     , QuickCheck >= 2.8+                     , nat-sized-numbers >= 0.1   ghc-options:         -threaded                        -rtsopts                        -with-rtsopts=-N
src/Data/Semiring.hs view
@@ -1,5 +1,9 @@ {-# LANGUAGE DefaultSignatures          #-}+{-# LANGUAGE TemplateHaskell            #-}+{-# LANGUAGE DeriveFoldable             #-}+{-# LANGUAGE DeriveFunctor              #-} {-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DeriveTraversable          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE StandaloneDeriving         #-} @@ -13,6 +17,12 @@  module Data.Semiring   ( Semiring(..)+  , StarSemiring(..)+  , HasPositiveInfinity(..)+  , HasNegativeInfinity(..)+  , PositiveInfinite(..)+  , NegativeInfinite(..)+  , Infinite(..)   , Add(..)   , Mul(..)   , add@@ -21,7 +31,6 @@   , Min(..)   ) where - import           Data.Functor.Const    (Const (..)) import           Data.Functor.Identity (Identity (..)) @@ -30,9 +39,6 @@ import           Data.Ratio            (Ratio) import           Numeric.Natural       (Natural) -import           Data.Set              (Set)-import qualified Data.Set              as Set- import           Data.Int              (Int16, Int32, Int64, Int8) import           Data.Word             (Word16, Word32, Word64, Word8) import           Foreign.C.Types       (CChar, CClock, CDouble, CFloat, CInt,@@ -54,9 +60,12 @@ import           GHC.Generics          (Generic, Generic1)  import           Data.Typeable         (Typeable)- import           Foreign.Storable      (Storable) +import           Data.Semiring.Infinite+import           Data.Semiring.TH++ -- | A <https://en.wikipedia.org/wiki/Semiring Semiring> is like the -- the combination of two 'Data.Monoid.Monoid's. The first -- is called '<+>'; it has the identity element 'zero', and it is@@ -80,161 +89,209 @@ -- -- == Annihilation -- @'zero' '<.>' a = a '<.>' 'zero' = 'zero'@-class Semiring a where-  -- | The identity of '<+>'.-  zero :: a-  -- | The identity of '<.>'.-  one :: a-  -- | An associative binary operation, which distributes over '<+>'.-  infixl 7 <.>-  (<.>) :: a -> a -> a-  -- | An associative, commutative binary operation.-  infixl 6 <+>-  (<+>) :: a -> a -> a--  default zero :: Num a => a-  default one :: Num a => a-  default (<+>) :: Num a => a -> a -> a-  default (<.>) :: Num a => a -> a -> a+--+-- An ordered semiring follows the laws:+-- @x '<=' y => x '<+>' z '<=' y '<+>' z@+-- @x '<=' y => x '<+>' z '<=' y '<+>' z@+-- @'zero' '<=' z '&&' x '<=' y => x '<.>' z '<=' y '<.>' z '&&' z '<.>' x '<=' z '<.>' y@+class Semiring a  where+    -- | The identity of '<+>'.+    zero+        :: a+    -- | The identity of '<.>'.+    one+        :: a+    -- | An associative binary operation, which distributes over '<+>'.+    infixl 7 <.>+    (<.>) :: a -> a -> a+    -- | An associative, commutative binary operation.+    infixl 6 <+>+    (<+>) :: a -> a -> a+    default zero :: Num a => a+    default one :: Num a => a+    default (<+>) :: Num a => a -> a -> a+    default (<.>) :: Num a => a -> a -> a+    zero = 0+    {-# INLINE zero #-}+    one = 1+    {-# INLINE one #-}+    (<+>) = (+)+    {-# INLINE (<+>) #-}+    (<.>) = (*)+    {-# INLINE (<.>) #-} -  zero = 0-  one = 1-  (<+>) = (+)-  (<.>) = (*)+-- | A <https://en.wikipedia.org/wiki/Semiring#Star_semirings Star semiring>+-- adds one operation, 'star' to a 'Semiring', such that it follows the+-- law:+--+-- @'star' x = 'one' '<+>' x '<.>' 'star' x = 'one' '<+>' 'star' x '<.>' x@+--+-- For the semiring of types, this is equivalent to a list. When looking+-- at the 'Applicative' and 'Control.Applicative.Alternative' classes as+-- (near-) semirings, this is equivalent to the+-- 'Control.Applicative.many' operation.+--+-- Another operation, 'plus', can be defined in relation to 'star':+--+-- @'plus' x = x '<.>' 'star' x@+--+-- This should be recognizable as a non-empty list on types, or the+-- 'Control.Applicative.some' operation in+-- 'Control.Applicative.Alternative'.+class Semiring a =>+      StarSemiring a  where+    {-# MINIMAL star | plus #-}+    star :: a -> a+    plus :: a -> a+    star x = one <+> plus x+    plus x = x <.> star x  ------------------------------------------------------------------------ -- Instances ------------------------------------------------------------------------+type CoerceBinary a b = (a -> a -> a) -> b -> b -> b+ instance Semiring Bool where-  one = True-  zero = False-  (<+>) = (||)-  (<.>) = (&&)+    one = True+    zero = False+    (<+>) = (||)+    (<.>) = (&&)+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} -instance Semiring () where-  one = ()-  zero = ()-  _ <+> _ = ()-  _ <.> _ = ()+instance StarSemiring Bool where+    star _ = True+    plus = id+    {-# INLINE star #-}+    {-# INLINE plus #-} -cartProd :: (Ord a, Monoid a) => Set a -> Set a -> Set a-cartProd xs ys =-  Set.foldl' (\a x ->-                Set.foldl' (flip (Set.insert . mappend x)) a ys)-  Set.empty xs+-- | Not lawful. Only for convenience.+instance Semiring a =>+         Semiring (NegativeInfinite a) where+    one = pure one+    zero = pure zero+    (<+>) =+        (coerce :: CoerceBinary (NegativeInfinite (Add a)) (NegativeInfinite a))+            mappend+    (<.>) = liftA2 (<.>)+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} --- | The 'Set' 'Semiring' is 'Data.Set.union' for '<+>', and a Cartesian--- product for '<.>'.-instance (Ord a, Monoid a) => Semiring (Set a) where-  (<.>) = cartProd-  (<+>) = Set.union-  zero = Set.empty-  one = Set.singleton mempty+-- | Not lawful. Only for convenience.+instance Semiring a =>+         Semiring (PositiveInfinite a) where+    one = pure one+    zero = pure zero+    (<+>) =+        (coerce :: CoerceBinary (PositiveInfinite (Add a)) (PositiveInfinite a))+            mappend+    (<.>) = liftA2 (<.>)+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} +-- | Not lawful. Only for convenience.+instance Semiring a =>+         Semiring (Infinite a) where+    one = pure one+    zero = pure zero+    (<+>) = (coerce :: CoerceBinary (Infinite (Add a)) (Infinite a)) mappend+    (<.>) = liftA2 (<.>)+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-}++instance (Eq a, Semiring a) =>+         StarSemiring (PositiveInfinite a) where+    star (PosFinite x)+      | x == zero = one+    star _ = PositiveInfinity++instance Semiring () where+    one = ()+    zero = ()+    _ <+> _ = ()+    _ <.> _ = ()+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-}++instance StarSemiring () where+    star _ = ()+    plus _ = ()+    {-# INLINE star #-}+    {-# INLINE plus #-}+ -- | A polynomial in /x/ can be defined as a list of its coefficients, -- where the /i/th element is the coefficient of /x^i/. This is the -- semiring for such a list. Adapted from <https://pdfs.semanticscholar.org/702d/348c32133997e992db362a19697d5607ab32.pdf here>.-instance Semiring a => Semiring [a] where-  one = [one]-  zero = []-  [] <+> ys = ys-  xs <+> [] = xs-  (x:xs) <+> (y:ys) = (x <+> y) : (xs <+> ys)-  [] <.> _ = []-  _ <.> [] = []-  (x:xs) <.> (y:ys) =-    (x <.> y) : (map (x <.>) ys <+> map (<.> y) xs <+> (xs <.> ys))+instance Semiring a =>+         Semiring [a] where+    one = [one]+    zero = []+    [] <+> ys = ys+    xs <+> [] = xs+    (x:xs) <+> (y:ys) = (x <+> y) : (xs <+> ys)+    [] <.> _ = []+    _ <.> [] = []+    (x:xs) <.> (y:ys) =+        (x <.> y) : (map (x <.>) ys <+> map (<.> y) xs <+> (xs <.> ys))  ------------------------------------------------------------------------ -- Addition and multiplication newtypes ------------------------------------------------------------------------- type WrapBinary f a = (a -> a -> a) -> f a -> f a -> f a  -- | Monoid under '<+>'. Analogous to 'Data.Monoid.Sum', but uses the -- 'Semiring' constraint, rather than 'Num'. newtype Add a = Add-  { getAdd :: a-  } deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num-             ,Enum, Typeable, Storable, Fractional, Real, RealFrac)+    { getAdd :: a+    } deriving (Eq,Ord,Read,Show,Bounded,Generic,Generic1,Num,Enum,Typeable+               ,Storable,Fractional,Real,RealFrac,Functor,Foldable,Traversable+               ,Semiring,StarSemiring)  -- | Monoid under '<.>'. Analogous to 'Data.Monoid.Product', but uses the -- 'Semiring' constraint, rather than 'Num'. newtype Mul a = Mul-  { getMul :: a-  } deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num-             ,Enum, Typeable, Storable, Fractional, Real, RealFrac)--instance Functor Add where fmap = coerce--instance Functor Mul where fmap = coerce--instance Foldable Add where-  foldr =-    (coerce :: ((a -> b -> c) -> (b ->     a -> c))-            ->  (a -> b -> c) -> (b -> Add a -> c)-    ) flip-  foldl = coerce-  foldMap = coerce-  length = const 1--instance Foldable Mul where-  foldr =-    (coerce :: ((a -> b -> c) -> (b ->     a -> c))-            ->  (a -> b -> c) -> (b -> Mul a -> c)-    ) flip-  foldl = coerce-  foldMap = coerce-  length = const 1--instance Applicative Add where-  pure = coerce-  (<*>) =-    (coerce :: (    (a -> b) ->     a ->     b)-            -> (Add (a -> b) -> Add a -> Add b)-    ) ($)--instance Applicative Mul where-  pure = coerce-  (<*>) =-    (coerce :: (    (a -> b) ->     a ->     b)-            -> (Mul (a -> b) -> Mul a -> Mul b)-    ) ($)--instance Monad Add where (>>=) = flip coerce--instance Monad Mul where (>>=) = flip coerce--instance Semiring a => Semigroup (Add a) where-  (<>) = (coerce :: WrapBinary Add a) (<+>)--instance Semiring a => Semigroup (Mul a) where-  (<>) = (coerce :: WrapBinary Mul a) (<.>)+    { getMul :: a+    } deriving (Eq,Ord,Read,Show,Bounded,Generic,Generic1,Num,Enum,Typeable+               ,Storable,Fractional,Real,RealFrac,Functor,Foldable,Traversable+               ,Semiring,StarSemiring) -instance Semiring a => Monoid (Add a) where-  mempty = Add zero-  mappend = (<>)+instance Semiring a =>+         Semigroup (Add a) where+    (<>) = (coerce :: WrapBinary Add a) (<+>)+    {-# INLINE (<>) #-} -instance Semiring a => Monoid (Mul a) where-  mempty = Mul one-  mappend = (<>)+instance Semiring a =>+         Semigroup (Mul a) where+    (<>) = (coerce :: WrapBinary Mul a) (<.>)+    {-# INLINE (<>) #-} -instance Semiring a => Semiring (Add a) where-  zero = Add zero-  one = Add one-  (<+>) = (coerce :: WrapBinary Add a) (<+>)-  (<.>) = (coerce :: WrapBinary Add a) (<.>)+instance Semiring a =>+         Monoid (Add a) where+    mempty = Add zero+    mappend = (<>)+    {-# INLINE mempty #-}+    {-# INLINE mappend #-} -instance Semiring a => Semiring (Mul a) where-  zero = Mul zero-  one = Mul one-  (<+>) = (coerce :: WrapBinary Mul a) (<+>)-  (<.>) = (coerce :: WrapBinary Mul a) (<.>)+instance Semiring a =>+         Monoid (Mul a) where+    mempty = Mul one+    mappend = (<>)+    {-# INLINE mempty #-}+    {-# INLINE mappend #-}  ------------------------------------------------------------------------ -- Addition and multiplication folds ------------------------------------------------------------------------- -- | Takes the sum of the elements of a 'Foldable'. Analogous to 'sum' -- on numbers, or 'or' on 'Bool's. --@@ -246,7 +303,9 @@ -- True -- >>> add [True, undefined] -- True-add :: (Foldable f, Semiring a) => f a -> a+add+    :: (Foldable f, Semiring a)+    => f a -> a add = getAdd . foldMap Add  -- | Takes the product of the elements of a 'Foldable'. Analogous to@@ -260,13 +319,14 @@ -- False -- >>> mul [False, undefined] -- False-mul :: (Foldable f, Semiring a) => f a -> a+mul+    :: (Foldable f, Semiring a)+    => f a -> a mul = getMul . foldMap Mul  ------------------------------------------------------------------------ -- Ord wrappers ------------------------------------------------------------------------- -- | The "<https://ncatlab.org/nlab/show/tropical+semiring Tropical>" or -- min-plus semiring. It is a semiring where: --@@ -283,11 +343,9 @@ -- Taking ∞ to be 'maxBound' would break the above law. Using 'Nothing' -- to represent it follows the law. newtype Min a = Min-  { getMin :: Maybe a-  } deriving (Eq, Read, Show, Generic, Generic1, Functor, Foldable-             ,Typeable)-  -- } deriving (Eq, Ord, Read, Show, Generic, Generic1, Functor-  --            ,Foldable)+    { getMin :: a+    } deriving (Eq,Ord,Read,Show,Bounded,Generic,Generic1,Num,Enum,Typeable+               ,Storable,Fractional,Real,RealFrac,Functor,Foldable,Traversable)  -- | The "<https://ncatlab.org/nlab/show/max-plus+algebra Arctic>" -- or max-plus semiring. It is a semiring where:@@ -305,103 +363,91 @@ -- Taking -∞ to be 'minBound' would break the above law. Using 'Nothing' -- to represent it follows the law. newtype Max a = Max-  { getMax :: Maybe a-  } deriving (Eq, Read, Show, Generic, Generic1, Functor, Foldable-             ,Typeable)--instance Ord a => Ord (Min a) where-  compare (Min Nothing) (Min Nothing)   = EQ-  compare (Min Nothing) _               = LT-  compare _ (Min Nothing)               = GT-  compare (Min (Just x)) (Min (Just y)) = compare x y--instance Ord a => Ord (Max a) where-  compare (Max Nothing) (Max Nothing)   = EQ-  compare (Max Nothing) _               = GT-  compare _ (Max Nothing)               = LT-  compare (Max (Just x)) (Max (Just y)) = compare x y---instance Applicative Max where-  pure = (coerce :: (a -> Maybe a) -> (a -> Max a)) Just-  (<*>) = (coerce :: (Maybe (a -> b) -> Maybe a -> Maybe b)-                  ->  Max   (a -> b) -> Max   a -> Max   b-          ) (<*>)--instance Applicative Min where-  pure = (coerce :: (a -> Maybe a) -> (a -> Min a)) Just-  (<*>) = (coerce :: (Maybe (a -> b) -> Maybe a -> Maybe b)-                  ->  Min   (a -> b) -> Min   a -> Min   b-          ) (<*>)--instance Monad Max where-  (>>=) = (coerce :: (Maybe a -> (a -> Maybe b) -> Maybe b)-                  ->  Max   a -> (a -> Max   b) -> Max   b-          ) (>>=)--instance Monad Min where-  (>>=) = (coerce :: (Maybe a -> (a -> Maybe b) -> Maybe b)-                  ->  Min   a -> (a -> Min   b) -> Min   b-          ) (>>=)+    { getMax :: a+    } deriving (Eq,Ord,Read,Show,Bounded,Generic,Generic1,Num,Enum,Typeable+               ,Storable,Fractional,Real,RealFrac,Functor,Foldable,Traversable) -instance Ord a => Semigroup (Max a) where-  Max Nothing <> x = x-  x <> Max Nothing = x-  Max (Just x) <> Max (Just y) = (Max . Just) (max x y)+instance Ord a =>+         Semigroup (Max a) where+    (<>) = (coerce :: WrapBinary Max a) max+    {-# INLINE (<>) #-} -instance Ord a => Semigroup (Min a) where-  Min Nothing <> x = x-  x <> Min Nothing = x-  Min (Just x) <> Min (Just y) = (Min . Just) (min x y)+instance Ord a =>+         Semigroup (Min a) where+    (<>) = (coerce :: WrapBinary Min a) min+    {-# INLINE (<>) #-} --- | >>> (getMax . foldMap pure) [1..10]--- Just 10-instance Ord a => Monoid (Max a) where-  mempty = Max Nothing-  mappend = (<>)+-- | >>> (getMax . foldMap Max) [1..10]+-- 10.0+instance (Ord a, HasNegativeInfinity a) =>+         Monoid (Max a) where+    mempty = Max negativeInfinity+    mappend = (<>)+    {-# INLINE mempty #-}+    {-# INLINE mappend #-} --- | >>> (getMin . foldMap pure) [1..10]--- Just 1-instance Ord a => Monoid (Min a) where-  mempty = Min Nothing-  mappend = (<>)+-- | >>> (getMin . foldMap Min) [1..10]+-- 1.0+instance (Ord a, HasPositiveInfinity a) =>+         Monoid (Min a) where+    mempty = Min positiveInfinity+    mappend = (<>)+    {-# INLINE mempty #-}+    {-# INLINE mappend #-} -instance (Semiring a, Ord a) => Semiring (Max a) where-  (<+>) = mappend-  zero = mempty-  (<.>) = liftA2 (<+>)-  one = Max (Just zero)+instance (Semiring a, Ord a, HasNegativeInfinity a) =>+         Semiring (Max a) where+    (<+>) = mappend+    zero = mempty+    (<.>) = (coerce :: WrapBinary Max a) (<+>)+    one = Max zero+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} -instance (Semiring a, Ord a) => Semiring (Min a) where-  (<+>) = mappend-  zero = mempty-  (<.>) = liftA2 (<+>)-  one = Min (Just zero)+instance (Semiring a, Ord a, HasPositiveInfinity a) =>+         Semiring (Min a) where+    (<+>) = mappend+    zero = mempty+    (<.>) = (coerce :: WrapBinary Min a) (<+>)+    one = Min zero+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} -instance Bounded a => Bounded (Min a) where-  maxBound = Min (Just maxBound)-  minBound = Min Nothing+instance (Semiring a, Ord a, HasPositiveInfinity a, HasNegativeInfinity a) =>+         StarSemiring (Max a) where+    star (Max x)+      | x > zero = Max positiveInfinity+      | otherwise = Max zero -instance Bounded a => Bounded (Max a) where-  minBound = Max (Just minBound)-  maxBound = Max Nothing+instance (Semiring a, Ord a, HasPositiveInfinity a, HasNegativeInfinity a) =>+         StarSemiring (Min a) where+    star (Min x)+      | x < zero = Min negativeInfinity+      | otherwise = Min zero  ------------------------------------------------------------------------ -- (->) instance ------------------------------------------------------------------------- -- | The @(->)@ instance is analogous to the one for 'Monoid'.-instance Semiring b => Semiring (a -> b) where-  zero = const zero-  one = const one-  (f <+> g) x = f x <+> g x-  (f <.> g) x = f x <.> g x+instance Semiring b =>+         Semiring (a -> b) where+    zero = const zero+    one = const one+    (f <+> g) x = f x <+> g x+    (f <.> g) x = f x <.> g x +instance StarSemiring b =>+         StarSemiring (a -> b) where+    star f x = star (f x)+    plus f x = plus (f x)  ------------------------------------------------------------------------ -- Endo instance ------------------------------------------------------------------------- -- | This is /not/ a true semiring. In particular, it requires the -- underlying monoid to be commutative, and even then, it is only a near -- semiring. It is, however, extremely useful. For instance, this type:@@ -410,28 +456,67 @@ -- -- 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-  Endo f <+> Endo g = Endo (f `mappend` g)-  one = mempty-  (<.>) = mappend+instance Monoid a =>+         Semiring (Endo a) where+    zero = Endo mempty+    Endo f <+> Endo g = Endo (f `mappend` g)+    one = mempty+    (<.>) = mappend+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} +instance (Monoid a, Eq a) =>+         StarSemiring (Endo a) where+    star (Endo f) = Endo converge+      where+        converge x = go x+          where+            go inp =+                mappend+                    x+                    (if inp == next+                         then inp+                         else go next)+              where+                next = mappend x (f inp)+ ------------------------------------------------------------------------ -- Instances for Bool wrappers ------------------------------------------------------------------------- instance Semiring Any where-  (<+>) = coerce (||)-  zero = Any False-  (<.>) = coerce (&&)-  one = Any True+    (<+>) = coerce (||)+    zero = Any False+    (<.>) = coerce (&&)+    one = Any True+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} +instance StarSemiring Any where+    star _ = Any True+    plus = id+    {-# INLINE star #-}+    {-# INLINE plus #-}+ instance Semiring All where-  (<+>) = coerce (||)-  zero = All False-  (<.>) = coerce (&&)-  one = All True+    (<+>) = coerce (||)+    zero = All False+    (<.>) = coerce (&&)+    one = All True+    {-# INLINE zero #-}+    {-# INLINE one #-}+    {-# INLINE (<+>) #-}+    {-# INLINE (<.>) #-} +instance StarSemiring All where+    star _ = All True+    plus = id+    {-# INLINE star #-}+    {-# INLINE plus #-}+ ------------------------------------------------------------------------ -- Boring instances ------------------------------------------------------------------------@@ -502,38 +587,6 @@ ------------------------------------------------------------------------ -- Very boring instances -------------------------------------------------------------------------instance (Semiring a, Semiring b) => Semiring (a,b) where-        zero = (zero, zero)-        (a1,b1) <+> (a2,b2) =-                (a1 <+> a2, b1 <+> b2)-        one = (one, one)-        (a1,b1) <.> (a2,b2) =-                (a1 <.> a2, b1 <.> b2) -instance (Semiring a, Semiring b, Semiring c) => Semiring (a,b,c) where-        zero = (zero, zero, zero)-        (a1,b1,c1) <+> (a2,b2,c2) =-                (a1 <+> a2, b1 <+> b2, c1 <+> c2)-        one = (one, one, one)-        (a1,b1,c1) <.> (a2,b2,c2) =-                (a1 <.> a2, b1 <.> b2, c1 <.> c2)--instance (Semiring a, Semiring b, Semiring c, Semiring d) => Semiring (a,b,c,d) where-        zero = (zero, zero, zero, zero)-        (a1,b1,c1,d1) <+> (a2,b2,c2,d2) =-                (a1 <+> a2, b1 <+> b2,-                 c1 <+> c2, d1 <+> d2)-        one = (one, one, one, one)-        (a1,b1,c1,d1) <.> (a2,b2,c2,d2) =-                (a1 <.> a2, b1 <.> b2, c1 <.> c2, d1 <.> d2)--instance (Semiring a, Semiring b, Semiring c, Semiring d, Semiring e) =>-                Semiring (a,b,c,d,e) where-        zero = (zero, zero, zero, zero, zero)-        (a1,b1,c1,d1,e1) <+> (a2,b2,c2,d2,e2) =-                (a1 <+> a2, b1 <+> b2, c1 <+> c2,-                 d1 <+> d2, e1 <+> e2)-        one = (one, one, one, one, one)-        (a1,b1,c1,d1,e1) <.> (a2,b2,c2,d2,e2) =-                (a1 <.> a2, b1 <.> b2, c1 <.> c2,-                 d1 <.> d2, e1 <.> e2)+$(traverse semiringIns [2..9])+$(traverse starIns [2..9])
+ src/Data/Semiring/Infinite.hs view
@@ -0,0 +1,274 @@+{-# LANGUAGE DefaultSignatures   #-}+{-# LANGUAGE DeriveFoldable      #-}+{-# LANGUAGE DeriveFunctor       #-}+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE DeriveTraversable   #-}+{-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Data.Semiring.Infinite+  ( HasPositiveInfinity(..)+  , HasNegativeInfinity(..)+  , NegativeInfinite(..)+  , PositiveInfinite(..)+  , Infinite(..)+  ) where++import           Foreign.C.Types     (CDouble, CFloat)++import           Control.Applicative (liftA2)+import           Data.Typeable       (Typeable)+import           GHC.Generics        (Generic, Generic1)++import           Data.Word           (Word8)+import           Foreign.Ptr         (Ptr, castPtr)+import           Foreign.Storable    (Storable, alignment, peek, peekByteOff,+                                      poke, pokeByteOff, sizeOf)++import           Data.Coerce+import           Data.Monoid++class HasPositiveInfinity a where+  positiveInfinity :: a+  default positiveInfinity :: RealFloat a => a+  positiveInfinity = 1/0++class HasNegativeInfinity a where+  negativeInfinity :: a+  default negativeInfinity :: RealFloat a => a+  negativeInfinity = negate (1/0)++instance HasPositiveInfinity Double+instance HasNegativeInfinity Double+instance HasPositiveInfinity Float+instance HasNegativeInfinity Float+instance HasPositiveInfinity CDouble+instance HasNegativeInfinity CDouble+instance HasPositiveInfinity CFloat+instance HasNegativeInfinity CFloat++data NegativeInfinite a+  = NegativeInfinity+  | NegFinite !a+  deriving (Eq, Ord, Read, Show, Generic, Generic1, Typeable, Functor+           ,Foldable, Traversable)++data PositiveInfinite a+  = PosFinite !a+  | PositiveInfinity+  deriving (Eq, Ord, Read, Show, Generic, Generic1, Typeable, Functor+           ,Foldable, Traversable)++instance Applicative NegativeInfinite where+  pure = NegFinite+  {-# INLINE pure #-}+  NegFinite f <*> NegFinite x = NegFinite (f x)+  _ <*> _ = NegativeInfinity+  {-# INLINE (<*>) #-}++instance Applicative PositiveInfinite where+  pure = PosFinite+  {-# INLINE pure #-}+  PosFinite f <*> PosFinite x = PosFinite (f x)+  _ <*> _ = PositiveInfinity+  {-# INLINE (<*>) #-}++data Infinite a+  = Negative+  | Finite !a+  | Positive+  deriving (Eq, Ord, Read, Show, Generic, Generic1, Typeable, Functor+           ,Foldable, Traversable)++instance Applicative Infinite where+  pure = Finite+  {-# INLINE pure #-}+  Finite f <*> Finite x = Finite (f x)+  Negative <*> Negative = Positive+  Negative <*> _ = Negative+  _ <*> Negative = Negative+  _ <*> _ = Positive+  {-# INLINE (<*>) #-}++instance Bounded a => Bounded (NegativeInfinite a) where+  {-# INLINE minBound #-}+  {-# INLINE maxBound #-}+  minBound = NegativeInfinity+  maxBound = pure maxBound++instance Bounded a => Bounded (PositiveInfinite a) where+  {-# INLINE minBound #-}+  {-# INLINE maxBound #-}+  minBound = pure minBound+  maxBound = PositiveInfinity++instance Bounded (Infinite a) where+  {-# INLINE minBound #-}+  {-# INLINE maxBound #-}+  minBound = Negative+  maxBound = Positive++instance HasNegativeInfinity (NegativeInfinite a) where+  {-# INLINE negativeInfinity #-}+  negativeInfinity = NegativeInfinity++instance HasPositiveInfinity (PositiveInfinite a) where+  {-# INLINE positiveInfinity #-}+  positiveInfinity = PositiveInfinity++instance HasNegativeInfinity (Infinite a) where+  {-# INLINE negativeInfinity #-}+  negativeInfinity = Negative++instance HasPositiveInfinity (Infinite a) where+  {-# INLINE positiveInfinity #-}+  positiveInfinity = Positive++instance (Enum a, Bounded a, Eq a) => Enum (NegativeInfinite a) where+  succ = foldr (const . pure . succ) (pure minBound)+  pred NegativeInfinity = error "Predecessor of negative infinity"+  pred (NegFinite x) | x == minBound = NegativeInfinity+                     | otherwise = NegFinite (pred x)+  toEnum 0 = NegativeInfinity+  toEnum n = NegFinite (toEnum (n-1))+  fromEnum = foldr (const . succ . fromEnum) 0+  enumFrom NegativeInfinity = NegativeInfinity : map pure [minBound..]+  enumFrom (NegFinite x)    = map pure [x..]++maxBoundOf :: Bounded a => f a -> a+maxBoundOf _ = maxBound++instance (Enum a, Bounded a, Eq a) => Enum (PositiveInfinite a) where+  pred = foldr (const . pure . pred) (pure maxBound)+  succ PositiveInfinity = error "Successor of positive infinity"+  succ (PosFinite x) | x == maxBound = PositiveInfinity+                     | otherwise = PosFinite (succ x)+  toEnum n+    | n == toEnum (maxBoundOf PositiveInfinity) + 1 = PositiveInfinity+    | otherwise = PosFinite (toEnum n)+  fromEnum p@PositiveInfinity = fromEnum (maxBoundOf p) + 1+  fromEnum (PosFinite x)      = fromEnum x+  enumFrom PositiveInfinity = [PositiveInfinity]+  enumFrom (PosFinite x)    = map pure [x..] ++ [PositiveInfinity]++instance (Enum a, Bounded a, Eq a) => Enum (Infinite a) where+  pred Negative = error "Predecessor of negative infinity"+  pred Positive = Finite maxBound+  pred (Finite x) | x == minBound = Negative+                  | otherwise = Finite (pred x)+  succ Negative = Finite minBound+  succ Positive = error "Successor of positive infinity"+  succ (Finite x) | x == maxBound = Positive+                  | otherwise = Finite (succ x)+  toEnum 0 = Negative+  toEnum n | n == toEnum (maxBoundOf Positive) + 2 = Positive+           | otherwise = Finite (toEnum (n-1))+  fromEnum Negative   = 0+  fromEnum (Finite x) = fromEnum x + 1+  fromEnum p@Positive = fromEnum (maxBoundOf p) + 1+  enumFrom Positive   = [Positive]+  enumFrom Negative   = Negative : map pure [minBound..] ++ [Positive]+  enumFrom (Finite x) = map pure (enumFrom x) ++ [Positive]++instance Monoid a => Monoid (NegativeInfinite a) where+  {-# INLINE mempty #-}+  {-# INLINE mappend #-}+  mempty = pure mempty+  mappend = liftA2 mappend++instance Monoid a => Monoid (PositiveInfinite a) where+  {-# INLINE mempty #-}+  {-# INLINE mappend #-}+  mempty = pure mempty+  mappend = liftA2 mappend++instance Monoid a => Monoid (Infinite a) where+  {-# INLINE mempty #-}+  {-# INLINE mappend #-}+  mempty = pure mempty+  Negative `mappend` Positive = Positive+  Positive `mappend` Negative = Positive+  Finite x `mappend` Finite y = pure (x `mappend` y)+  Negative `mappend` _ = Negative+  Positive `mappend` _ = Positive+  _ `mappend` y = y++instance Num a => Num (NegativeInfinite a) where+  fromInteger = pure . fromInteger+  (+) = liftA2 (+)+  (*) = liftA2 (*)+  abs = fmap abs+  signum = foldr (const . pure . signum) (-1)+  (-) = liftA2 (-)++instance Num a => Num (PositiveInfinite a) where+  fromInteger = pure . fromInteger+  (+) = liftA2 (+)+  (*) = liftA2 (*)+  abs = fmap abs+  signum = foldr (const . pure . signum) (-1)+  (-) = liftA2 (-)++type CoerceBinary a b = (a -> a -> a) -> (b -> b -> b)++instance Num a => Num (Infinite a) where+  fromInteger = Finite . fromInteger+  (+) = (coerce :: CoerceBinary (Infinite (Sum a)) (Infinite a)) mappend+  (*) = liftA2 (*)+  signum Positive   = 1+  signum Negative   = -1+  signum (Finite x) = Finite (signum x)+  negate Positive   = Negative+  negate Negative   = Positive+  negate (Finite x) = Finite (negate x)+  abs Negative = Positive+  abs x = fmap abs x++-- Adapted from https://www.schoolofhaskell.com/user/snoyberg/random-code-snippets/storable-instance-of-maybe+instance Storable a => Storable (NegativeInfinite a) where+    sizeOf x = sizeOf (strip x) + 1+    alignment x = alignment (strip x)+    peek ptr = (peekByteOff ptr . sizeOf . strip . stripPtr) ptr >>= \case+      (1 :: Word8) -> NegFinite <$> peek (stripFPtr ptr)+      _ -> pure NegativeInfinity+    poke ptr NegativeInfinity+      = pokeByteOff ptr ((sizeOf . strip . stripPtr) ptr) (0 :: Word8)+    poke ptr (NegFinite a)+      = poke (stripFPtr ptr) a+     *> pokeByteOff ptr (sizeOf a) (1 :: Word8)++instance Storable a => Storable (PositiveInfinite a) where+    sizeOf x = sizeOf (strip x) + 1+    alignment x = alignment (strip x)+    peek ptr = (peekByteOff ptr . sizeOf . strip . stripPtr) ptr >>= \case+      (1 :: Word8) -> PosFinite <$> peek (stripFPtr ptr)+      _ -> pure PositiveInfinity+    poke ptr PositiveInfinity+      = pokeByteOff ptr ((sizeOf . strip . stripPtr) ptr) (0 :: Word8)+    poke ptr (PosFinite a)+      = poke (stripFPtr ptr) a+     *> pokeByteOff ptr (sizeOf a) (1 :: Word8)++instance Storable a => Storable (Infinite a) where+    sizeOf x = sizeOf (strip x) + 1+    alignment x = alignment (strip x)+    peek ptr = (peekByteOff ptr . sizeOf . strip . stripPtr) ptr >>= \case+      (0 :: Word8) -> Finite <$> peek (stripFPtr ptr)+      1 -> pure Negative+      _ -> pure Positive+    poke ptr Positive+      = pokeByteOff ptr ((sizeOf . strip . stripPtr) ptr) (2 :: Word8)+    poke ptr Negative+      = pokeByteOff ptr ((sizeOf . strip . stripPtr) ptr) (1 :: Word8)+    poke ptr (Finite a)+      = poke (stripFPtr ptr) a+     *> pokeByteOff ptr (sizeOf a) (1 :: Word8)++strip :: f a -> a+strip _ = error "strip"++stripFPtr :: Ptr (f a) -> Ptr a+stripFPtr = castPtr++stripPtr :: Ptr a -> a+stripPtr _ = error "stripPtr"
src/Data/Semiring/Numeric.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DeriveFoldable             #-} {-# LANGUAGE DeriveFunctor              #-} {-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE DeriveTraversable          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}  {-|@@ -36,13 +37,18 @@ newtype Bottleneck a = Bottleneck   { getBottleneck :: a   } deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num-             ,Enum, Typeable, Storable, Fractional, Real, RealFrac)+             ,Enum, Typeable, Storable, Fractional, Real, RealFrac+             ,Functor, Foldable, Traversable)  instance (Bounded a, Ord a) => Semiring (Bottleneck a) where   (<+>) = (coerce :: WrapBinary Bottleneck a) max   (<.>) = (coerce :: WrapBinary Bottleneck a) min   zero = Bottleneck minBound   one  = Bottleneck maxBound+  {-# INLINE (<+>) #-}+  {-# INLINE (<.>) #-}+  {-# INLINE zero #-}+  {-# INLINE one #-}  -- | Positive numbers only. --@@ -53,7 +59,8 @@ newtype Division a = Division   { getDivision :: a   } deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num-             ,Enum, Typeable, Storable, Fractional, Real, RealFrac)+             ,Enum, Typeable, Storable, Fractional, Real, RealFrac+             ,Functor, Foldable, Traversable)  -- | Only expects positive numbers instance (Integral a, Semiring a) => Semiring (Division a) where@@ -61,6 +68,10 @@   (<.>) = (coerce :: WrapBinary Division a) lcm   zero = Division zero   one = Division one+  {-# INLINE (<+>) #-}+  {-# INLINE (<.>) #-}+  {-# INLINE zero #-}+  {-# INLINE one #-}  -- | <https://en.wikipedia.org/wiki/Semiring#cite_ref-droste_14-0 Wikipedia> -- has some information on this. Also@@ -74,13 +85,18 @@ newtype Łukasiewicz a = Łukasiewicz   { getŁukasiewicz :: a   } deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num-             ,Enum, Typeable, Storable, Fractional, Real, RealFrac)+             ,Enum, Typeable, Storable, Fractional, Real, RealFrac+             ,Functor, Foldable, Traversable)  instance (Ord a, Num a) => Semiring (Łukasiewicz a) where   (<+>) = (coerce :: WrapBinary Łukasiewicz a) max   (<.>) = (coerce :: WrapBinary Łukasiewicz a) (\x y -> max 0 (x + y - 1))   zero = Łukasiewicz 0   one  = Łukasiewicz 1+  {-# INLINE (<+>) #-}+  {-# INLINE (<.>) #-}+  {-# INLINE zero #-}+  {-# INLINE one #-}  -- | <https://en.wikipedia.org/wiki/Semiring#cite_ref-droste_14-0 Wikipedia> -- has some information on this. Also@@ -94,115 +110,37 @@ newtype Viterbi a = Viterbi   { getViterbi :: a   } deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num-             ,Enum, Typeable, Storable, Fractional, Real, RealFrac)+             ,Enum, Typeable, Storable, Fractional, Real, RealFrac+             ,Functor, Foldable, Traversable)  instance (Ord a, Semiring a) => Semiring (Viterbi a) where   (<+>) = (coerce :: WrapBinary Viterbi a) max   (<.>) = (coerce :: WrapBinary Viterbi a) (<.>)   zero = Viterbi zero   one  = Viterbi one+  {-# INLINE (<+>) #-}+  {-# INLINE (<.>) #-}+  {-# INLINE zero #-}+  {-# INLINE one #-}  -- | Useful for optimizing multiplication, or working with large numbers. -- -- @('<.>')   = ('+') --x '<+>' y = -('log' ('exp' (-x) + 'exp' (-y)))---'zero'    = ∞ -- represented by 'Nothing'+--'zero'    = ∞ --'one'     = 0@ newtype Log a = Log-  { getLog :: Maybe a-  } deriving (Eq, Read, Show, Generic, Generic1, Typeable, Functor-             ,Foldable, Applicative, Monad)--instance (Semiring a, Floating a) => Semiring (Log a) where-  zero = Log Nothing-  one = Log (Just zero)-  Log (Just x) <.> Log (Just y) = Log (Just (x + y))-  _ <.> _ = Log Nothing-  Log Nothing <+> y = y-  x <+> Log Nothing = x-  Log (Just x) <+> Log (Just y)-    = Log (Just (-(log (exp (-x) + exp (-y)))))--instance Ord a => Ord (Log a) where-  compare (Log Nothing) (Log Nothing)   = EQ-  compare (Log Nothing) _               = LT-  compare _ (Log Nothing)               = GT-  compare (Log (Just x)) (Log (Just y)) = compare x y----------------------------------------------------------------------------- Boring instances---------------------------------------------------------------------------instance Functor Bottleneck where fmap = coerce-instance Functor Division where fmap = coerce-instance Functor Łukasiewicz where fmap = coerce-instance Functor Viterbi where fmap = coerce--instance Foldable Bottleneck where-  foldr   =-    (coerce :: ((a -> b -> c) -> (b -> a -> c))-            -> (a -> b -> c)-            -> (b -> Bottleneck a -> c)) flip-  foldl   = coerce-  foldMap = coerce-  length  = const 1-  null _ = False--instance Foldable Division where-  foldr   =-    (coerce :: ((a -> b -> c) -> (b -> a -> c))-            -> (a -> b -> c)-            -> (b -> Division a -> c)) flip-  foldl   = coerce-  foldMap = coerce-  length  = const 1-  null _ = False--instance Foldable Łukasiewicz where-  foldr =-    (coerce :: ((a -> b -> c) -> (b -> a -> c))-            -> (a -> b -> c)-            -> (b -> Łukasiewicz a -> c)) flip-  foldl   = coerce-  foldMap = coerce-  length  = const 1-  null _ = False--instance Foldable Viterbi where-  foldr =-    (coerce :: ((a -> b -> c) -> (b -> a -> c))-            -> (a -> b -> c)-            -> (b -> Viterbi a -> c)) flip-  foldl   = coerce-  foldMap = coerce-  length  = const 1-  null _ = False--instance Applicative Bottleneck where-  pure = coerce-  (<*>) =-    (coerce :: ((a -> b) -> a -> b)-            -> (Bottleneck (a -> b) -> Bottleneck a -> Bottleneck b)) ($)--instance Applicative Łukasiewicz where-  pure = coerce-  (<*>) =-    (coerce :: ((a -> b) -> a -> b)-            -> (Łukasiewicz (a -> b) -> Łukasiewicz a -> Łukasiewicz b)) ($)--instance Applicative Division where-  pure = coerce-  (<*>) =-    (coerce :: ((a -> b) -> a -> b)-            -> (Division (a -> b) -> Division a -> Division b)) ($)--instance Applicative Viterbi where-  pure = coerce-  (<*>) =-    (coerce :: ((a -> b) -> a -> b)-            -> (Viterbi (a -> b) -> Viterbi a -> Viterbi b)) ($)+  { getLog :: a+  } deriving (Eq, Ord, Read, Show, Generic, Generic1, Typeable, Functor+             ,Foldable) -instance Monad Bottleneck where (>>=) = flip coerce-instance Monad Division where (>>=) = flip coerce-instance Monad Łukasiewicz where (>>=) = flip coerce-instance Monad Viterbi where (>>=) = flip coerce+instance (Floating a, HasPositiveInfinity a) => Semiring (Log a) where+  zero = Log positiveInfinity+  one = Log 0+  (<.>) = (coerce :: WrapBinary Log a) (+)+  Log x <+> Log y+    = Log (-(log (exp (-x) + exp (-y))))+  {-# INLINE (<+>) #-}+  {-# INLINE (<.>) #-}+  {-# INLINE zero #-}+  {-# INLINE one #-}
+ src/Data/Semiring/TH.hs view
@@ -0,0 +1,43 @@+module Data.Semiring.TH where++import Control.Monad+import Language.Haskell.TH++repN :: Int -> String -> Q Dec+repN n nm = do+    let v = VarP (mkName nm)+    rhs <- TupE <$> replicateM n (pure (VarE (mkName nm)))+    return $ ValD v (NormalB rhs) []++appN :: Int -> String -> Q Dec+appN n nm = do+    let f = VarE (mkName nm)+    xs <- replicateM n (newName "x")+    let args = [TupP (map VarP xs)]+        ntup = TupE (map (AppE f . VarE) xs)+    return $ FunD (mkName nm) [Clause args (NormalB ntup) []]++cmbN :: Int -> String -> Q Dec+cmbN n nm = do+    let f = VarE (mkName nm)+    xs <- replicateM n (newName "x")+    ys <- replicateM n (newName "y")+    let args = [TupP (map VarP xs), TupP (map VarP ys)]+        ntup = TupE (zipWith (AppE . AppE f) (map VarE xs) (map VarE ys))+    return $ FunD (mkName nm) [Clause args (NormalB ntup) []]++starIns :: Int -> Q Dec+starIns n = do+    names <- replicateM n (newName "a")+    let c = ConT (mkName "StarSemiring")+        ct = map (AppT c . VarT) names+    InstanceD Nothing ct (AppT c $ foldl AppT (TupleT n) (map VarT names)) <$>+        sequence [appN n "star", appN n "plus"]++semiringIns :: Int -> Q Dec+semiringIns n = do+    names <- replicateM n (newName "a")+    let c = ConT (mkName "Semiring")+        ct = map (AppT c . VarT) names+    InstanceD Nothing ct (AppT c $ foldl AppT (TupleT n) (map VarT names)) <$>+        sequence [cmbN n "<+>", cmbN n "<.>", repN n "zero", repN n "one"]
src/Test/Semiring.hs view
@@ -20,9 +20,15 @@   , unaryLaws   , binaryLaws   , ternaryLaws+  , starLaw+  , plusLaw+  , starLaws+  , nearUnLaws+  , nearTernaryLaws+  , ordLaws   ) where -import           Data.Semiring   (Semiring (..))+import           Data.Semiring   (Semiring (..), StarSemiring (..))  -- | Plus is associative. plusAssoc :: (Eq a, Semiring a, Show a) => a -> a -> a -> Either String String@@ -102,7 +108,7 @@   l = (x <+> y) <.> z   r = x <.> z <+> y <.> z   s = unlines-    [ "<.> does " ++ (if res then "" else "not ") ++ "distribute left over <+>."+    [ "<.> does " ++ (if res then "" else "not ") ++ "distribute right over <+>."     , "    Law:"     , "        (x <+> y) <.> z = x <.> z <+> y <.> z"     , "    x = " ++ show x@@ -159,6 +165,16 @@ unaryLaws :: (Eq a, Semiring a, Show a) => a -> Either String String unaryLaws x = fmap unlines (sequence [plusId x, mulId x, annihilate x]) +nearUnLaws :: (Eq a, Semiring a, Show a) => a -> Either String String+nearUnLaws = plusId++nearTernaryLaws :: (Eq a, Semiring a, Show a)+            => a -> a -> a -> Either String String+nearTernaryLaws x y z =+  fmap unlines (sequence [ plusAssoc x y z+                         , mulAssoc x y z+                         , mulDistribL x y z])+ binaryLaws :: (Eq a, Semiring a, Show a)            => a -> a -> Either String String binaryLaws = plusComm@@ -170,3 +186,68 @@                          , mulAssoc x y z                          , mulDistribL x y z                          , mulDistribR x y z])++starLaw :: (Eq a, StarSemiring a, Show a) => a -> Either String String+starLaw (x :: a) = if res then Right s else Left s where+  res = l == st && r == st+  l = one <+> x <.> star x+  r = one <+> star x <.> x+  st = star x+  s = unlines+    [ "star law" ++ (if res then "" else " not") ++ " followed."+    , "    Law:"+    , "        star x = one <+> x <.> star x = one <+> star x <.> x"+    , "    x = " ++ show x+    , "    one = " ++ show (one :: a)+    , "    star x = " ++ show st+    , "    one <+> x <.> star x = " ++ show l+    , "    one <+> star x <.> x = " ++ show r ]++plusLaw :: (Eq a, StarSemiring a, Show a) => a -> Either String String+plusLaw (x :: a) = if res then Right s else Left s where+  res = r == st+  r = x <.> star x+  st = plus x+  s = unlines+    [ "plus law" ++ (if res then "" else " not") ++ " followed."+    , "    Law:"+    , "        plus x = x <.> star x"+    , "    x = " ++ show x+    , "    star x = " ++ show st+    , "    x <.> star x = " ++ show r ]++starLaws :: (Eq a, StarSemiring a, Show a) => a -> Either String String+starLaws x = fmap unlines (sequence [starLaw x, plusLaw x])+++ordAddLaw :: (Ord a, Semiring a, Show a) => a -> a -> a -> Either String String+ordAddLaw (x :: a) (y :: a) (z :: a) = if res then Right s else Left s where+  cnd = x <= y+  lhs = x <+> z <= y <+> z+  rhs = z <+> x <= z <+> y+  res = not cnd || lhs && rhs+  s = unlines+    [ "ordering law" ++ (if res then "" else " not") ++ " followed."+    , "    Law:"+    , "        x <= y => x <+> z <= y <+> z && z <+> x <= z <+> y"+    , "    x = " ++ show x+    , "    y = " ++ show y+    , "    z = " ++ show z ]++ordMulLaw :: (Ord a, Semiring a, Show a) => a -> a -> a -> Either String String+ordMulLaw (x :: a) (y :: a) (z :: a) = if res then Right s else Left s where+  cnd = x <= y && zero <= z+  lhs = x <.> z <= y <.> z+  rhs = z <.> x <= z <.> y+  res = not cnd || lhs && rhs+  s = unlines+    [ "ordering law" ++ (if res then "" else " not") ++ " followed."+    , "    Law:"+    , "        x <= y => x <.> z <= y <.> z && z <.> x <= z <.> y"+    , "    x = " ++ show x+    , "    y = " ++ show y+    , "    z = " ++ show z ]+++ordLaws :: (Ord a, Semiring a, Show a) => a -> a -> a -> Either String String+ordLaws x y z = fmap unlines (sequence [ordAddLaw x y z, ordMulLaw x y z])
test/Spec.hs view
@@ -1,31 +1,34 @@+{-# LANGUAGE DataKinds                  #-} {-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses      #-} {-# LANGUAGE ScopedTypeVariables        #-} {-# LANGUAGE TypeOperators              #-}-{-# LANGUAGE DataKinds                  #-}-{-# LANGUAGE KindSignatures             #-}+{-# OPTIONS_GHC -fno-warn-orphans       #-}  module Main (main) where  import           Control.Applicative-import           Control.Arrow          (first)+import           Control.Arrow            (first)+import           Data.Bool import           Data.Foldable-import           Data.IntMap.Strict     (IntMap)-import qualified Data.IntMap.Strict     as IntMap-import qualified Data.Map.Strict        as Map+import           Data.Function+import           Data.IntMap.Strict       (IntMap)+import qualified Data.IntMap.Strict       as IntMap+import qualified Data.Map.Strict          as Map import           Data.Monoid import           Data.Semiring import           Data.Semiring.Free import           Data.Semiring.Numeric-import qualified Data.Set               as Set+import           GHC.TypeLits+import           Numeric.Sized.WordOfSize import           Test.DocTest+import           Test.QuickCheck          hiding (Positive (..), generate,+                                           (.&.)) import           Test.Semiring-import           Test.SmallCheck-import           Test.SmallCheck.Series-import           GHC.TypeLits-import           Data.Function-import           Data.Bits+import           Test.SmallCheck          hiding (Testable, (==>))+import           Test.SmallCheck.Series   hiding (Positive)+import qualified Test.SmallCheck.Series   as SC  ------------------------------------------------------------------------ @@ -35,41 +38,132 @@   smallCheck 1000 (unaryLaws   :: UnaryLaws   Integer)   smallCheck 100  (binaryLaws  :: BinaryLaws  Integer)   smallCheck 10   (ternaryLaws :: TernaryLaws Integer)+  smallCheck 10   (ordLaws     :: TernaryLaws Integer) -  putStrLn "(WordN 2)"-  smallCheck 16  (unaryLaws   :: UnaryLaws   (WordN 2))-  smallCheck 16  (binaryLaws  :: BinaryLaws  (WordN 2))-  smallCheck 16  (ternaryLaws :: TernaryLaws (WordN 2))+  putStrLn "(WordOfSize 2)"+  smallCheck 16  (unaryLaws   :: UnaryLaws   (WordOfSize 2))+  smallCheck 16  (binaryLaws  :: BinaryLaws  (WordOfSize 2))+  smallCheck 16  (ternaryLaws :: TernaryLaws (WordOfSize 2))+  smallCheck 16  (starLaws    :: UnaryLaws   (PositiveInfinite (WordOfSize 2))) -  putStrLn "(WordN 2,WordN 2)"-  smallCheck 16 (unaryLaws   :: UnaryLaws   (WordN 2,WordN 2))-  smallCheck 14 (binaryLaws  :: BinaryLaws  (WordN 2,WordN 2))-  smallCheck 8  (ternaryLaws :: TernaryLaws (WordN 2,WordN 2))+  putStrLn "(WordOfSize 2,WordOfSize 2)"+  smallCheck 16 (unaryLaws   :: UnaryLaws   (WordOfSize 2,WordOfSize 2))+  smallCheck 14 (binaryLaws  :: BinaryLaws  (WordOfSize 2,WordOfSize 2))+  smallCheck 8  (ternaryLaws :: TernaryLaws (WordOfSize 2,WordOfSize 2))+  smallCheck 16 (starLaws    :: UnaryLaws   (PositiveInfinite (WordOfSize 2)+                                            ,PositiveInfinite (WordOfSize 2))) -  putStrLn "(WordN 2,WordN 2,WordN 2)"-  smallCheck 10 (unaryLaws   :: UnaryLaws   (WordN 2,WordN 2,WordN 2))-  smallCheck 5  (binaryLaws  :: BinaryLaws  (WordN 2,WordN 2,WordN 2))-  smallCheck 2  (ternaryLaws :: TernaryLaws (WordN 2,WordN 2,WordN 2))+  putStrLn "(WordOfSize 2,WordOfSize 2,WordOfSize 2)"+  smallCheck 10 (unaryLaws   :: UnaryLaws   (WordOfSize 2,WordOfSize 2,WordOfSize 2))+  smallCheck 5  (binaryLaws  :: BinaryLaws  (WordOfSize 2,WordOfSize 2,WordOfSize 2))+  smallCheck 2  (ternaryLaws :: TernaryLaws (WordOfSize 2,WordOfSize 2,WordOfSize 2))+  smallCheck 10 (starLaws    :: UnaryLaws   (PositiveInfinite (WordOfSize 2)+                                            ,PositiveInfinite (WordOfSize 2)+                                            ,PositiveInfinite (WordOfSize 2))) -  putStrLn "(WordN 2,WordN 2,WordN 2,WordN 2)"-  smallCheck 8 (unaryLaws   :: UnaryLaws   (WordN 2,WordN 2,WordN 2,WordN 2))-  smallCheck 4 (binaryLaws  :: BinaryLaws  (WordN 2,WordN 2,WordN 2,WordN 2))-  smallCheck 1 (ternaryLaws :: TernaryLaws (WordN 2,WordN 2,WordN 2,WordN 2))+  putStrLn "(WordOfSize 2,WordOfSize 2,WordOfSize 2,WordOfSize 2)"+  smallCheck 8 (unaryLaws   :: UnaryLaws   (WordOfSize 2,WordOfSize 2,WordOfSize 2,WordOfSize 2))+  smallCheck 4 (binaryLaws  :: BinaryLaws  (WordOfSize 2,WordOfSize 2,WordOfSize 2,WordOfSize 2))+  smallCheck 1 (ternaryLaws :: TernaryLaws (WordOfSize 2,WordOfSize 2,WordOfSize 2,WordOfSize 2))+  smallCheck 16 (starLaws    :: UnaryLaws   (PositiveInfinite (WordOfSize 2)+                                            ,PositiveInfinite (WordOfSize 2)+                                            ,PositiveInfinite (WordOfSize 2)+                                            ,PositiveInfinite (WordOfSize 2))) +  putStrLn "(Int,Int,Int,Int,Int)"+  quickCheck (unaryLaws   :: UnaryLaws   (Int,Int,Int,Int,Int))+  quickCheck (binaryLaws  :: BinaryLaws  (Int,Int,Int,Int,Int))+  quickCheck (ternaryLaws :: TernaryLaws (Int,Int,Int,Int,Int))+  quickCheck (starLaws    :: UnaryLaws   (PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int))++  putStrLn "(Int,Int,Int,Int,Int,Int)"+  quickCheck (unaryLaws   :: UnaryLaws   (Int,Int,Int,Int,Int,Int))+  quickCheck (binaryLaws  :: BinaryLaws  (Int,Int,Int,Int,Int,Int))+  quickCheck (ternaryLaws :: TernaryLaws (Int,Int,Int,Int,Int,Int))+  quickCheck (starLaws    :: UnaryLaws   (PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int))++  putStrLn "(Int,Int,Int,Int,Int,Int,Int)"+  quickCheck (unaryLaws   :: UnaryLaws   (Int,Int,Int,Int,Int,Int,Int))+  quickCheck (binaryLaws  :: BinaryLaws  (Int,Int,Int,Int,Int,Int,Int))+  quickCheck (ternaryLaws :: TernaryLaws (Int,Int,Int,Int,Int,Int,Int))+  quickCheck (starLaws    :: UnaryLaws   (PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int))++  putStrLn "(Int,Int,Int,Int,Int,Int,Int,Int)"+  quickCheck (unaryLaws   :: UnaryLaws   (Int,Int,Int,Int,Int,Int,Int,Int))+  quickCheck (binaryLaws  :: BinaryLaws  (Int,Int,Int,Int,Int,Int,Int,Int))+  quickCheck (ternaryLaws :: TernaryLaws (Int,Int,Int,Int,Int,Int,Int,Int))+  quickCheck (starLaws    :: UnaryLaws   (PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int))++  putStrLn "(Int,Int,Int,Int,Int,Int,Int,Int,Int)"+  quickCheck (unaryLaws   :: UnaryLaws   (Int,Int,Int,Int,Int,Int,Int,Int,Int))+  quickCheck (binaryLaws  :: BinaryLaws  (Int,Int,Int,Int,Int,Int,Int,Int,Int))+  quickCheck (ternaryLaws :: TernaryLaws (Int,Int,Int,Int,Int,Int,Int,Int,Int))+  quickCheck (starLaws    :: UnaryLaws   (PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int+                                         ,PositiveInfinite Int))+   putStrLn "Int"   smallCheck 1000 (unaryLaws   :: UnaryLaws   Int)   smallCheck 100  (binaryLaws  :: BinaryLaws  Int)   smallCheck 10   (ternaryLaws :: TernaryLaws Int) +  putStrLn "PosInf Integer"+  smallCheck 1000 (nearUnLaws      :: UnaryLaws   (PositiveInfinite Integer))+  smallCheck 100  (binaryLaws      :: BinaryLaws  (PositiveInfinite Integer))+  smallCheck 10   (nearTernaryLaws :: TernaryLaws (PositiveInfinite Integer))+  smallCheck 10   (ordLaws         :: TernaryLaws (PositiveInfinite Integer))++  putStrLn "NegInf Integer"+  smallCheck 1000 (nearUnLaws      :: UnaryLaws   (NegativeInfinite Integer))+  smallCheck 100  (binaryLaws      :: BinaryLaws  (NegativeInfinite Integer))+  smallCheck 10   (nearTernaryLaws :: TernaryLaws (NegativeInfinite Integer))+  smallCheck 10   (ordLaws         :: TernaryLaws (NegativeInfinite Integer))++  -- putStrLn "Inf Integer"+  -- smallCheck 1000 (nearUnLaws      :: UnaryLaws   (Infinite Integer))+  -- smallCheck 100  (binaryLaws      :: BinaryLaws  (Infinite Integer))+  -- smallCheck 10   (nearTernaryLaws :: TernaryLaws (Infinite Integer))+  -- smallCheck 10   (ordLaws         :: TernaryLaws (Infinite Integer))+   putStrLn "()"   smallCheck 1 (unaryLaws   :: UnaryLaws   ())   smallCheck 1 (binaryLaws  :: BinaryLaws  ())   smallCheck 1 (ternaryLaws :: TernaryLaws ())+  smallCheck 1 (starLaws    :: UnaryLaws   ())    putStrLn "Bool"   smallCheck 2 (unaryLaws   :: UnaryLaws   Bool)   smallCheck 4 (binaryLaws  :: BinaryLaws  Bool)   smallCheck 8 (ternaryLaws :: TernaryLaws Bool)+  smallCheck 2 (starLaws    :: UnaryLaws   Bool)    putStrLn "Any"   smallCheck 2 (unLawsOn   Any :: UnaryLaws   Bool)@@ -81,40 +175,37 @@   smallCheck 4 (binLawsOn  All :: BinaryLaws  Bool)   smallCheck 8 (ternLawsOn All :: TernaryLaws Bool) -  putStrLn "[WordN 2]"-  smallCheck 5 (unaryLaws   :: UnaryLaws   [WordN 2])-  smallCheck 4 (binaryLaws  :: BinaryLaws  [WordN 2])-  smallCheck 3 (ternaryLaws :: TernaryLaws [WordN 2])--  putStrLn "Set [WordN 2]"-  smallCheck 4 (unLawsOn   Set.fromList :: UnaryLaws   [[WordN 2]])-  smallCheck 3 (binLawsOn  Set.fromList :: BinaryLaws  [[WordN 2]])-  smallCheck 3 (ternLawsOn Set.fromList :: TernaryLaws [[WordN 2]])+  putStrLn "[WordOfSize 2]"+  smallCheck 5 (unaryLaws   :: UnaryLaws   [WordOfSize 2])+  smallCheck 4 (binaryLaws  :: BinaryLaws  [WordOfSize 2])+  smallCheck 3 (ternaryLaws :: TernaryLaws [WordOfSize 2])    putStrLn "Min Integer"-  smallCheck 1000 (unLawsOn   Min :: UnaryLaws   (Maybe Integer))-  smallCheck 100  (binLawsOn  Min :: BinaryLaws  (Maybe Integer))-  smallCheck 10   (ternLawsOn Min :: TernaryLaws (Maybe Integer))+  smallCheck 1000 (unLawsOn   Min :: UnaryLaws   (PositiveInfinite Integer))+  smallCheck 100  (binLawsOn  Min :: BinaryLaws  (PositiveInfinite Integer))+  smallCheck 10   (ternLawsOn Min :: TernaryLaws (PositiveInfinite Integer))+  smallCheck 1000 (starLaws . Min :: UnaryLaws   (Infinite    Integer))    putStrLn "Max Integer"-  smallCheck 1000 (unLawsOn   Max :: UnaryLaws   (Maybe Integer))-  smallCheck 100  (binLawsOn  Max :: BinaryLaws  (Maybe Integer))-  smallCheck 10   (ternLawsOn Max :: TernaryLaws (Maybe Integer))+  smallCheck 1000 (unLawsOn   Max :: UnaryLaws   (NegativeInfinite Integer))+  smallCheck 100  (binLawsOn  Max :: BinaryLaws  (NegativeInfinite Integer))+  smallCheck 10   (ternLawsOn Max :: TernaryLaws (NegativeInfinite Integer))+  smallCheck 1000 (starLaws . Max :: UnaryLaws   (Infinite    Integer)) -  putStrLn "Free (WordN 2)"-  smallCheck 4 (unLawsOn   Free :: UnaryLaws   [[WordN 2]])-  smallCheck 3 (binLawsOn  Free :: BinaryLaws  [[WordN 2]])-  smallCheck 3 (ternLawsOn Free :: TernaryLaws [[WordN 2]])+  putStrLn "Free (WordOfSize 2)"+  smallCheck 4 (unLawsOn   Free :: UnaryLaws   [[WordOfSize 2]])+  smallCheck 3 (binLawsOn  Free :: BinaryLaws  [[WordOfSize 2]])+  smallCheck 3 (ternLawsOn Free :: TernaryLaws [[WordOfSize 2]]) -  putStrLn "Bottleneck (WordN 2)"-  smallCheck 1000 (unLawsOn   Bottleneck :: UnaryLaws   (WordN 2))-  smallCheck 100  (binLawsOn  Bottleneck :: BinaryLaws  (WordN 2))-  smallCheck 10   (ternLawsOn Bottleneck :: TernaryLaws (WordN 2))+  putStrLn "Bottleneck (WordOfSize 2)"+  smallCheck 1000 (unLawsOn   Bottleneck :: UnaryLaws   (WordOfSize 2))+  smallCheck 100  (binLawsOn  Bottleneck :: BinaryLaws  (WordOfSize 2))+  smallCheck 10   (ternLawsOn Bottleneck :: TernaryLaws (WordOfSize 2))    putStrLn "Division Integer"-  smallCheck 1000 (unLawsOn   (Division . getPositive) :: UnaryLaws   (Positive Integer))-  smallCheck 100  (binLawsOn  (Division . getPositive) :: BinaryLaws  (Positive Integer))-  smallCheck 10   (ternLawsOn (Division . getPositive) :: TernaryLaws (Positive Integer))+  smallCheck 1000 (unLawsOn   (Division . getPositive) :: UnaryLaws   (SC.Positive Integer))+  smallCheck 100  (binLawsOn  (Division . getPositive) :: BinaryLaws  (SC.Positive Integer))+  smallCheck 10   (ternLawsOn (Division . getPositive) :: TernaryLaws (SC.Positive Integer))    putStrLn "Łukasiewicz Double"   smallCheck 1000 (unLawsOn   Łukasiewicz :: UnaryLaws   Fraction)@@ -127,15 +218,19 @@   smallCheck 10   (ternLawsOn Viterbi :: TernaryLaws Fraction)    putStrLn "Log Double"-  smallCheck 1000 (unLawsOn   Log :: UnaryLaws   (Maybe Fraction))-  smallCheck 100  (binLawsOn  Log :: BinaryLaws  (Maybe Fraction))-  smallCheck 10   (ternLawsOn Log :: TernaryLaws (Maybe Fraction))+  quickCheck (unLawsOn   Log :: UnaryLaws   (Approx Double))+  quickCheck (binLawsOn  Log :: BinaryLaws  (Approx Double))+  quickCheck (ternLawsOn Log :: TernaryLaws (Approx Double))    putStrLn "Bool -> Bool"   smallCheck 3 (unLawsOn   fromFunc :: UnaryLaws   (Bool -> Bool))   smallCheck 2 (binLawsOn  fromFunc :: BinaryLaws  (Bool -> Bool))   smallCheck 2 (ternLawsOn fromFunc :: TernaryLaws (Bool -> Bool))+  quickCheck (unLawsOn   fromFunc :: UnaryLaws   (Bool -> Bool))+  quickCheck (binLawsOn  fromFunc :: BinaryLaws  (Bool -> Bool))+  quickCheck (ternLawsOn fromFunc :: TernaryLaws (Bool -> Bool)) +   putStrLn "Endo (Add Bool)"   smallCheck 3 (unOn plusId        eFromFunc :: UnaryLaws   (Bool -> Bool))   smallCheck 3 (unOn mulId         eFromFunc :: UnaryLaws   (Bool -> Bool))@@ -179,17 +274,38 @@ -- Serial wrappers  -- | A type with a serial instance between zero and one-newtype Fraction-  = Fraction Double-  deriving (Show, Num, Fractional, Real, RealFrac, Floating, RealFloat, Semiring)+newtype Fraction =+    Fraction Double+    deriving (Show,Num,Fractional,Real,RealFrac,Floating,RealFloat,Semiring) +newtype Approx a =+    Approx a+    deriving (Show,Num,Fractional,Real,RealFrac,Floating,RealFloat,Semiring+             ,HasPositiveInfinity)++instance (Arbitrary a, Num a, Ord a) => Arbitrary (Approx a) where+  arbitrary = fmap Approx (suchThat arbitrary ((<100).abs))+ instance Eq Fraction where-  Fraction x == Fraction y = abs (x-y) < 0.011+    Fraction x == Fraction y = abs (x - y) < 0.011 +instance (RealFloat a, Ord a) =>+         Eq (Approx a) where+    Approx x == Approx y =+        isInfinite x && isInfinite y ||+        x == y ||+        let n = abs (x - y)+        in max (n / abs x) (n / abs y) < 0.011++instance (RealFloat a, Ord a) => Ord (Approx a) where+    compare (Approx x) (Approx y)+      | Approx x == Approx y = EQ+      | otherwise = compare x y+ instance Ord Fraction where-  compare (Fraction x) (Fraction y)-    | Fraction x == Fraction y = EQ-    | otherwise = compare x y+    compare (Fraction x) (Fraction y)+      | Fraction x == Fraction y = EQ+      | otherwise = compare x y  instance Monad m => Serial m Fraction where   series = fmap Fraction $ generate (\d -> if d >= 0 then pure 0 else empty) <|> rest where@@ -197,50 +313,24 @@     go lower upper = let mid = (lower + upper) / 2 in       mid : interleave (go lower mid) (go mid upper)     interleave (x:xs) (y:ys) = x : y : interleave xs ys-    interleave _ _ = undefined---- | A very small numeric type for exhaustiveness-newtype WordN (n :: Nat) = WordN { getWordN :: Word } deriving Show--mask :: KnownNat n => WordN n -> Word-mask x = shift 1 (fromInteger (natVal x)) - 1--trunc :: KnownNat n => WordN n -> WordN n-trunc v@(WordN x) = WordN (x .&. mask v)--instance KnownNat n => Bounded (WordN n) where-  minBound = WordN 0-  maxBound = res where res = WordN (mask res)--instance KnownNat n => Num (WordN n) where-  WordN x + WordN y = trunc (WordN (x + y))-  WordN x * WordN y = trunc (WordN (x * y))-  WordN x - WordN y = trunc (WordN (x - y))-  fromInteger x = trunc (WordN (fromInteger x))-  abs = id-  signum (WordN x) = WordN (signum x)--instance KnownNat n => Eq (WordN n) where-  (==) = (==) `on` getWordN . trunc+    interleave _ _           = undefined -instance KnownNat n => Ord (WordN n) where-  compare = compare `on` getWordN . trunc+instance (Monad m, KnownNat n) => Serial m (WordOfSize n) where+  series = generate (`take` [minBound..maxBound]) -instance KnownNat n => Real (WordN n) where-  toRational = toRational . getWordN+instance KnownNat n => Arbitrary (WordOfSize n) where+  arbitrary = arbitraryBoundedEnum -instance KnownNat n => Enum (WordN n) where-  fromEnum = fromEnum . getWordN-  toEnum = trunc . WordN . toEnum+instance KnownNat n => Semiring (WordOfSize n) -instance KnownNat n => Integral (WordN n) where-  toInteger = toInteger . getWordN-  quotRem (WordN x) (WordN y) = (WordN (quot x y), WordN (rem x y))+instance (Monad m, Serial m a) => Serial m (PositiveInfinite a) where+  series = fmap (maybe PositiveInfinity PosFinite) series -instance (Monad m, KnownNat n) => Serial m (WordN n) where-  series = generate (`take` [minBound..maxBound])+instance (Monad m, Serial m a) => Serial m (NegativeInfinite a) where+  series = fmap (maybe NegativeInfinity NegFinite) series -instance KnownNat n => Semiring (WordN n)+instance (Monad m, Serial m a) => Serial m (Infinite a) where+  series = fmap (either (bool Positive Negative) Finite) series  ------------------------------------------------------------------------ -- Function Equality@@ -283,7 +373,7 @@     c = maybe 1 succ (Map.lookup e m)     nb = case b of       Just (a,d) | d >= c -> (a,d)-      _ -> (e,c)+      _          -> (e,c)  apply :: Enum a => Func a b -> a -> b apply (Func c cs) x = IntMap.findWithDefault c (fromEnum x) cs@@ -298,3 +388,64 @@   one = fromFunc one   f <+> g = fromFunc (apply f <+> apply g)   f <.> g = fromFunc (apply f <.> apply g)++------------------------------------------------------------------------+-- QuickCheck wrappers++instance Arbitrary a => Arbitrary (PositiveInfinite a) where+  arbitrary = fmap (maybe PositiveInfinity PosFinite) arbitrary++instance Arbitrary a => Arbitrary (NegativeInfinite a) where+  arbitrary = fmap (maybe NegativeInfinity NegFinite) arbitrary++instance Arbitrary a => Arbitrary (Infinite a) where+  arbitrary = fmap (either (bool Positive Negative) Finite) arbitrary++instance Testable (Either String String) where+  property = either (`counterexample` False) (const (property True))++instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e+         ,Arbitrary f)+  => Arbitrary (a,b,c,d,e,f) where+    arbitrary = (,,,,,) <$> arbitrary+                        <*> arbitrary+                        <*> arbitrary+                        <*> arbitrary+                        <*> arbitrary+                        <*> arbitrary++instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e+         ,Arbitrary f, Arbitrary g)+  => Arbitrary (a,b,c,d,e,f,g) where+    arbitrary = (,,,,,,) <$> arbitrary+                         <*> arbitrary+                         <*> arbitrary+                         <*> arbitrary+                         <*> arbitrary+                         <*> arbitrary+                         <*> arbitrary++instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e+         ,Arbitrary f, Arbitrary g, Arbitrary h)+  => Arbitrary (a,b,c,d,e,f,g,h) where+    arbitrary = (,,,,,,,) <$> arbitrary+                          <*> arbitrary+                          <*> arbitrary+                          <*> arbitrary+                          <*> arbitrary+                          <*> arbitrary+                          <*> arbitrary+                          <*> arbitrary++instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e+         ,Arbitrary f, Arbitrary g, Arbitrary h, Arbitrary i)+  => Arbitrary (a,b,c,d,e,f,g,h,i) where+    arbitrary = (,,,,,,,,) <$> arbitrary+                           <*> arbitrary+                           <*> arbitrary+                           <*> arbitrary+                           <*> arbitrary+                           <*> arbitrary+                           <*> arbitrary+                           <*> arbitrary+                           <*> arbitrary