gambler 0.1.0.0 → 0.2.0.0
raw patch · 10 files changed
+195/−29 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Fold.Effectful.Examples.Boring: all :: Monad m => (a -> Bool) -> EffectfulFold m a Bool
- Fold.Effectful.Examples.Boring: and :: Monad m => EffectfulFold m Bool Bool
- Fold.Effectful.Examples.Boring: any :: Monad m => (a -> Bool) -> EffectfulFold m a Bool
- Fold.Effectful.Examples.Boring: element :: Eq a => Monad m => a -> EffectfulFold m a Bool
- Fold.Effectful.Examples.Boring: elementIndex :: Eq a => Monad m => a -> EffectfulFold m a (Maybe Natural)
- Fold.Effectful.Examples.Boring: find :: Monad m => (a -> Bool) -> EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: findIndex :: Monad m => (a -> Bool) -> EffectfulFold m a (Maybe Natural)
- Fold.Effectful.Examples.Boring: first :: Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: index :: Monad m => Natural -> EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: last :: Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: length :: Monad m => EffectfulFold m a Natural
- Fold.Effectful.Examples.Boring: list :: Monad m => EffectfulFold m a [a]
- Fold.Effectful.Examples.Boring: lookup :: Eq a => Monad m => a -> EffectfulFold m (a, b) (Maybe b)
- Fold.Effectful.Examples.Boring: magma :: (a -> a -> a) -> Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: maximum :: Ord a => Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: maximumBy :: (a -> a -> Ordering) -> Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: mean :: Fractional a => Monad m => EffectfulFold m a a
- Fold.Effectful.Examples.Boring: minimum :: Ord a => Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: minimumBy :: (a -> a -> Ordering) -> Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: monoid :: Monoid a => Monad m => EffectfulFold m a a
- Fold.Effectful.Examples.Boring: notElement :: Eq a => Monad m => a -> EffectfulFold m a Bool
- Fold.Effectful.Examples.Boring: null :: Monad m => EffectfulFold m a Bool
- Fold.Effectful.Examples.Boring: or :: Monad m => EffectfulFold m Bool Bool
- Fold.Effectful.Examples.Boring: product :: Num a => Monad m => EffectfulFold m a a
- Fold.Effectful.Examples.Boring: reverseList :: Monad m => EffectfulFold m a [a]
- Fold.Effectful.Examples.Boring: semigroup :: Semigroup a => Monad m => EffectfulFold m a (Maybe a)
- Fold.Effectful.Examples.Boring: standardDeviation :: Floating a => Monad m => EffectfulFold m a a
- Fold.Effectful.Examples.Boring: sum :: Num a => Monad m => EffectfulFold m a a
- Fold.Effectful.Examples.Boring: variance :: Fractional a => Monad m => EffectfulFold m a a
- Fold.Effectful.Examples.Interesting: effect :: Monad m => (a -> m b) -> EffectfulFold m a ()
- Fold.Effectful.Examples.Interesting: effectMonoid :: (Monoid w, Monad m) => (a -> m w) -> EffectfulFold m a w
- Fold.Nonempty.Examples.Boring: all :: (a -> Bool) -> NonemptyFold a Bool
- Fold.Nonempty.Examples.Boring: and :: NonemptyFold Bool Bool
- Fold.Nonempty.Examples.Boring: any :: (a -> Bool) -> NonemptyFold a Bool
- Fold.Nonempty.Examples.Boring: element :: Eq a => a -> NonemptyFold a Bool
- Fold.Nonempty.Examples.Boring: elementIndex :: Eq a => a -> NonemptyFold a (Maybe Natural)
- Fold.Nonempty.Examples.Boring: find :: (a -> Bool) -> NonemptyFold a (Maybe a)
- Fold.Nonempty.Examples.Boring: findIndex :: (a -> Bool) -> NonemptyFold a (Maybe Natural)
- Fold.Nonempty.Examples.Boring: first :: NonemptyFold a a
- Fold.Nonempty.Examples.Boring: index :: Natural -> NonemptyFold a (Maybe a)
- Fold.Nonempty.Examples.Boring: length :: NonemptyFold a Natural
- Fold.Nonempty.Examples.Boring: list :: NonemptyFold a [a]
- Fold.Nonempty.Examples.Boring: lookup :: Eq a => a -> NonemptyFold (a, b) (Maybe b)
- Fold.Nonempty.Examples.Boring: mean :: Fractional a => NonemptyFold a a
- Fold.Nonempty.Examples.Boring: monoid :: Monoid a => NonemptyFold a a
- Fold.Nonempty.Examples.Boring: notElement :: Eq a => a -> NonemptyFold a Bool
- Fold.Nonempty.Examples.Boring: or :: NonemptyFold Bool Bool
- Fold.Nonempty.Examples.Boring: product :: Num a => NonemptyFold a a
- Fold.Nonempty.Examples.Boring: reverseList :: NonemptyFold a [a]
- Fold.Nonempty.Examples.Boring: standardDeviation :: Floating a => NonemptyFold a a
- Fold.Nonempty.Examples.Boring: sum :: Num a => NonemptyFold a a
- Fold.Nonempty.Examples.Boring: variance :: Fractional a => NonemptyFold a a
- Fold.Nonempty.Examples.Interesting: last :: NonemptyFold a a
- Fold.Nonempty.Examples.Interesting: list :: NonemptyFold a (NonEmpty a)
- Fold.Nonempty.Examples.Interesting: magma :: (a -> a -> a) -> NonemptyFold a a
- Fold.Nonempty.Examples.Interesting: maximum :: Ord a => NonemptyFold a a
- Fold.Nonempty.Examples.Interesting: maximumBy :: (a -> a -> Ordering) -> NonemptyFold a a
- Fold.Nonempty.Examples.Interesting: minimum :: Ord a => NonemptyFold a a
- Fold.Nonempty.Examples.Interesting: minimumBy :: (a -> a -> Ordering) -> NonemptyFold a a
- Fold.Nonempty.Examples.Interesting: reverseList :: NonemptyFold a (NonEmpty a)
- Fold.Nonempty.Examples.Interesting: semigroup :: Semigroup a => NonemptyFold a a
- Fold.Pure.Examples.Boring: all :: (a -> Bool) -> Fold a Bool
- Fold.Pure.Examples.Boring: and :: Fold Bool Bool
- Fold.Pure.Examples.Boring: any :: (a -> Bool) -> Fold a Bool
- Fold.Pure.Examples.Boring: element :: Eq a => a -> Fold a Bool
- Fold.Pure.Examples.Boring: elementIndex :: Eq a => a -> Fold a (Maybe Natural)
- Fold.Pure.Examples.Boring: find :: (a -> Bool) -> Fold a (Maybe a)
- Fold.Pure.Examples.Boring: findIndex :: (a -> Bool) -> Fold a (Maybe Natural)
- Fold.Pure.Examples.Boring: first :: Fold a (Maybe a)
- Fold.Pure.Examples.Boring: index :: Natural -> Fold a (Maybe a)
- Fold.Pure.Examples.Boring: last :: Fold a (Maybe a)
- Fold.Pure.Examples.Boring: lookup :: Eq a => a -> Fold (a, b) (Maybe b)
- Fold.Pure.Examples.Boring: magma :: (a -> a -> a) -> Fold a (Maybe a)
- Fold.Pure.Examples.Boring: maximum :: Ord a => Fold a (Maybe a)
- Fold.Pure.Examples.Boring: maximumBy :: (a -> a -> Ordering) -> Fold a (Maybe a)
- Fold.Pure.Examples.Boring: minimum :: Ord a => Fold a (Maybe a)
- Fold.Pure.Examples.Boring: minimumBy :: (a -> a -> Ordering) -> Fold a (Maybe a)
- Fold.Pure.Examples.Boring: notElement :: Eq a => a -> Fold a Bool
- Fold.Pure.Examples.Boring: null :: Fold a Bool
- Fold.Pure.Examples.Boring: or :: Fold Bool Bool
- Fold.Pure.Examples.Boring: semigroup :: Semigroup a => Fold a (Maybe a)
- Fold.Pure.Examples.Interesting: length :: Fold a Natural
- Fold.Pure.Examples.Interesting: list :: Fold a [a]
- Fold.Pure.Examples.Interesting: mean :: Fractional a => Fold a a
- Fold.Pure.Examples.Interesting: monoid :: Monoid a => Fold a a
- Fold.Pure.Examples.Interesting: product :: Num a => Fold a a
- Fold.Pure.Examples.Interesting: reverseList :: Fold a [a]
- Fold.Pure.Examples.Interesting: standardDeviation :: Floating a => Fold a a
- Fold.Pure.Examples.Interesting: sum :: Num a => Fold a a
- Fold.Pure.Examples.Interesting: variance :: Fractional a => Fold a a
- Fold.Shortcut.Examples.Boring: first :: ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: last :: ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: length :: ShortcutFold a Natural
- Fold.Shortcut.Examples.Boring: list :: ShortcutFold a [a]
- Fold.Shortcut.Examples.Boring: magma :: (a -> a -> a) -> ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: maximum :: Ord a => ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: maximumBy :: (a -> a -> Ordering) -> ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: mean :: Fractional a => ShortcutFold a a
- Fold.Shortcut.Examples.Boring: minimum :: Ord a => ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: minimumBy :: (a -> a -> Ordering) -> ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: monoid :: Monoid a => ShortcutFold a a
- Fold.Shortcut.Examples.Boring: product :: Num a => ShortcutFold a a
- Fold.Shortcut.Examples.Boring: reverseList :: ShortcutFold a [a]
- Fold.Shortcut.Examples.Boring: semigroup :: Semigroup a => ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Boring: standardDeviation :: Floating a => ShortcutFold a a
- Fold.Shortcut.Examples.Boring: sum :: Num a => ShortcutFold a a
- Fold.Shortcut.Examples.Boring: variance :: Fractional a => ShortcutFold a a
- Fold.Shortcut.Examples.Interesting: all :: (a -> Bool) -> ShortcutFold a Bool
- Fold.Shortcut.Examples.Interesting: and :: ShortcutFold Bool Bool
- Fold.Shortcut.Examples.Interesting: any :: (a -> Bool) -> ShortcutFold a Bool
- Fold.Shortcut.Examples.Interesting: element :: Eq a => a -> ShortcutFold a Bool
- Fold.Shortcut.Examples.Interesting: elementIndex :: Eq a => a -> ShortcutFold a (Maybe Natural)
- Fold.Shortcut.Examples.Interesting: find :: (a -> Bool) -> ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Interesting: findIndex :: (a -> Bool) -> ShortcutFold a (Maybe Natural)
- Fold.Shortcut.Examples.Interesting: index :: Natural -> ShortcutFold a (Maybe a)
- Fold.Shortcut.Examples.Interesting: lookup :: Eq a => a -> ShortcutFold (a, b) (Maybe b)
- Fold.Shortcut.Examples.Interesting: notElement :: Eq a => a -> ShortcutFold a Bool
- Fold.Shortcut.Examples.Interesting: null :: ShortcutFold a Bool
- Fold.Shortcut.Examples.Interesting: or :: ShortcutFold Bool Bool
- Fold.ShortcutNonempty.Examples.Boring: all :: (a -> Bool) -> ShortcutNonemptyFold a Bool
- Fold.ShortcutNonempty.Examples.Boring: and :: ShortcutNonemptyFold Bool Bool
- Fold.ShortcutNonempty.Examples.Boring: any :: (a -> Bool) -> ShortcutNonemptyFold a Bool
- Fold.ShortcutNonempty.Examples.Boring: element :: Eq a => a -> ShortcutNonemptyFold a Bool
- Fold.ShortcutNonempty.Examples.Boring: elementIndex :: Eq a => a -> ShortcutNonemptyFold a (Maybe Natural)
- Fold.ShortcutNonempty.Examples.Boring: find :: (a -> Bool) -> ShortcutNonemptyFold a (Maybe a)
- Fold.ShortcutNonempty.Examples.Boring: findIndex :: (a -> Bool) -> ShortcutNonemptyFold a (Maybe Natural)
- Fold.ShortcutNonempty.Examples.Boring: index :: Natural -> ShortcutNonemptyFold a (Maybe a)
- Fold.ShortcutNonempty.Examples.Boring: last :: ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: length :: ShortcutNonemptyFold a Natural
- Fold.ShortcutNonempty.Examples.Boring: list :: ShortcutNonemptyFold a [a]
- Fold.ShortcutNonempty.Examples.Boring: lookup :: Eq a => a -> ShortcutNonemptyFold (a, b) (Maybe b)
- Fold.ShortcutNonempty.Examples.Boring: magma :: (a -> a -> a) -> ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: maximum :: Ord a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: maximumBy :: (a -> a -> Ordering) -> ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: mean :: Fractional a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: minimum :: Ord a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: minimumBy :: (a -> a -> Ordering) -> ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: monoid :: Monoid a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: notElement :: Eq a => a -> ShortcutNonemptyFold a Bool
- Fold.ShortcutNonempty.Examples.Boring: or :: ShortcutNonemptyFold Bool Bool
- Fold.ShortcutNonempty.Examples.Boring: product :: Num a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: reverseList :: ShortcutNonemptyFold a [a]
- Fold.ShortcutNonempty.Examples.Boring: semigroup :: Semigroup a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: standardDeviation :: Floating a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: sum :: Num a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Boring: variance :: Fractional a => ShortcutNonemptyFold a a
- Fold.ShortcutNonempty.Examples.Interesting: first :: ShortcutNonemptyFold a a
Files
- changelog.md +13/−0
- gambler.cabal +17/−11
- source/Fold.hs +1/−1
- source/Fold/Nonempty/Examples/Boring.hs +2/−10
- source/Fold/Nonempty/Examples/Interesting.hs +10/−0
- source/Fold/ShortcutNonempty/Examples/Boring.hs +2/−2
- source/Fold/ShortcutNonempty/Examples/Interesting.hs +5/−1
- test/Positive.hs +127/−0
- test/Spec/Nonempty.hs +7/−0
- test/Spec/ShortcutNonempty.hs +11/−4
changelog.md view
@@ -1,3 +1,16 @@+## 0.2.0.0 (2023-02-22)++The "Examples" modules are no longer divided into "Interesting" and "Boring"+modules in the public API, because this leads to too many breaking releases.++`NonemptyFold` and `ShortcutNonemptyFold` now have their own `sum` and `product`+definitions instead of being lifted variants of the `Fold` and `ShortcutFold`+definitions. This makes it possible to use them with numeric types that do not+include additive or multiplicative identity values. For example, we now have a+test case which takes the sum over a non-empty list of positive integers. Since+a "positive integer" type does not include zero, previously this would result in+arithmetic underflow.+ ## 0.1.0.0 (2023-02-20) Adds `ShortcutFold` and `ShortcutNonemptyFold`.
gambler.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0 name: gambler-version: 0.1.0.0+version: 0.2.0.0 category: Streaming synopsis: Composable, streaming, and efficient left folds@@ -40,8 +40,6 @@ Fold.Pure Fold.Pure.Conversion Fold.Pure.Examples- Fold.Pure.Examples.Interesting- Fold.Pure.Examples.Boring Fold.Pure.Run Fold.Pure.Type Fold.Pure.Utilities@@ -49,8 +47,6 @@ Fold.Effectful Fold.Effectful.Conversion Fold.Effectful.Examples- Fold.Effectful.Examples.Interesting- Fold.Effectful.Examples.Boring Fold.Effectful.Run Fold.Effectful.Type Fold.Effectful.Utilities@@ -58,8 +54,6 @@ Fold.Nonempty Fold.Nonempty.Conversion Fold.Nonempty.Examples- Fold.Nonempty.Examples.Interesting- Fold.Nonempty.Examples.Boring Fold.Nonempty.Run Fold.Nonempty.Type Fold.Nonempty.Utilities@@ -68,8 +62,6 @@ Fold.Shortcut.Run Fold.Shortcut.Type Fold.Shortcut.Examples- Fold.Shortcut.Examples.Interesting- Fold.Shortcut.Examples.Boring Fold.Shortcut.Conversion Fold.Shortcut.Utilities @@ -77,14 +69,27 @@ Fold.ShortcutNonempty.Run Fold.ShortcutNonempty.Type Fold.ShortcutNonempty.Examples- Fold.ShortcutNonempty.Examples.Interesting- Fold.ShortcutNonempty.Examples.Boring Fold.ShortcutNonempty.Conversion Fold.ShortcutNonempty.Utilities other-modules: Strict + Fold.Pure.Examples.Interesting+ Fold.Pure.Examples.Boring++ Fold.Effectful.Examples.Interesting+ Fold.Effectful.Examples.Boring++ Fold.Nonempty.Examples.Interesting+ Fold.Nonempty.Examples.Boring++ Fold.Shortcut.Examples.Interesting+ Fold.Shortcut.Examples.Boring++ Fold.ShortcutNonempty.Examples.Interesting+ Fold.ShortcutNonempty.Examples.Boring+ test-suite test-gambler import: base hs-source-dirs: test@@ -96,6 +101,7 @@ Spec.Effectful Spec.Shortcut Spec.ShortcutNonempty+ Positive ghc-options: -threaded default-extensions:
source/Fold.hs view
@@ -27,7 +27,7 @@ import Fold.ShortcutNonempty.Type import Fold.Effectful.Examples.Interesting-import Fold.Nonempty.Examples.Interesting hiding (list, reverseList)+import Fold.Nonempty.Examples.Interesting hiding (list, reverseList, sum, product) import Fold.Pure.Examples.Interesting import Fold.Shortcut.Examples.Interesting import Fold.ShortcutNonempty.Examples.Interesting
source/Fold/Nonempty/Examples/Boring.hs view
@@ -5,7 +5,7 @@ {- * Monoid -} monoid, {- * Length -} length, {- * Boolean -} and, or, all, any,- {- * Numeric -} sum, product, mean, variance, standardDeviation,+ {- * Numeric -} mean, variance, standardDeviation, {- * Search -} element, notElement, find, lookup, {- * Index -} index, findIndex, elementIndex, {- * List -} list, reverseList,@@ -18,7 +18,7 @@ import Data.Monoid (Monoid) import Fold.Nonempty.Type (NonemptyFold) import Numeric.Natural (Natural)-import Prelude (Floating, Fractional, Num)+import Prelude (Floating, Fractional) import qualified Fold.Nonempty.Conversion as Convert import qualified Fold.Pure.Examples.Interesting as Pure@@ -52,14 +52,6 @@ {-| 'True' if any input satisfies the predicate -} any :: (a -> Bool) -> NonemptyFold a Bool any predicate = Convert.shortcutFold (Shortcut.any predicate)--{-| Adds the inputs -}-sum :: Num a => NonemptyFold a a-sum = Convert.fold Pure.sum--{-| Multiplies the inputs -}-product :: Num a => NonemptyFold a a-product = Convert.fold Pure.product {-| Numerically stable arithmetic mean of the inputs -} mean :: Fractional a => NonemptyFold a a
source/Fold/Nonempty/Examples/Interesting.hs view
@@ -3,6 +3,7 @@ {- * General -} magma, semigroup, {- * Endpoints -} last, {- * Extrema -} maximum, minimum, maximumBy, minimumBy,+ {- * Numeric -} sum, product, {- * List -} list, reverseList, ) where@@ -13,6 +14,7 @@ import Data.List.NonEmpty (NonEmpty ((:|))) import Data.Ord (Ord, Ordering (GT), max, min) import Data.Semigroup (Semigroup, (<>))+import Prelude (Num, (+), (*)) import qualified Strict @@ -44,6 +46,14 @@ {-| The least input with respect to the given comparison function -} minimumBy :: (a -> a -> Ordering) -> NonemptyFold a a minimumBy cmp = magma (\x y -> case cmp x y of { GT -> y; _ -> x })++{-| Adds the inputs -}+sum :: Num a => NonemptyFold a a+sum = magma (+)++{-| Multiplies the inputs -}+product :: Num a => NonemptyFold a a+product = magma (*) {-| All the inputs -} list :: NonemptyFold a (NonEmpty a)
source/Fold/ShortcutNonempty/Examples/Boring.hs view
@@ -55,11 +55,11 @@ {-| Adds the inputs (ambivalent) -} sum :: Num a => ShortcutNonemptyFold a a-sum = Convert.fold Pure.sum+sum = Convert.nonemptyFold Nonempty.sum {-| Multiplies the inputs (ambivalent) -} product :: Num a => ShortcutNonemptyFold a a-product = Convert.fold Pure.product+product = Convert.nonemptyFold Nonempty.product {-| Numerically stable arithmetic mean of the inputs (ambivalent) -} mean :: Fractional a => ShortcutNonemptyFold a a
source/Fold/ShortcutNonempty/Examples/Interesting.hs view
@@ -1,4 +1,8 @@-module Fold.ShortcutNonempty.Examples.Interesting where+module Fold.ShortcutNonempty.Examples.Interesting+ (+ {- * First/last -} first,+ )+ where import Fold.ShortcutNonempty.Type
+ test/Positive.hs view
@@ -0,0 +1,127 @@+module Positive (Positive) where++import Prelude (($), Enum, Eq, Ord, Show, (.), id)++import Numeric.Natural (Natural)+import Prelude (Int, Integer, Integral, Num, Real)++import qualified Control.Exception as Exception+import qualified Data.Bits as Bits+import qualified Data.List as List+import qualified Data.Maybe as Maybe+import qualified Data.Ord as Ord+import qualified Prelude as Enum (Enum (..))+import qualified Prelude as Num (Integral (..), Num (..), Real (..), fromIntegral)+import qualified Text.Show as Show++newtype Positive = FromNatural{ toNatural :: Natural } deriving (Eq, Ord)++fromNatural :: Natural -> Positive+fromNatural = FromNatural++fromNaturalChecked :: Natural -> Positive+fromNaturalChecked x = case x of 0 -> Exception.throw Exception.Underflow; _ -> fromNatural x++toInteger :: Positive -> Integer+toInteger = Num.toInteger . toNatural++fromInteger :: Integer -> Positive+fromInteger = fromNatural . Num.fromInteger++fromIntegerChecked :: Integer -> Positive+fromIntegerChecked x = if x Ord.>= 1 then fromInteger x else Exception.throw Exception.Underflow++add :: Positive -> Positive -> Positive+add a b = fromNatural (toNatural a Num.+ toNatural b)++subtract :: Positive -> Positive -> Positive+subtract a b = fromNatural (toNatural a Num.- toNatural b)++subtractChecked :: Positive -> Positive -> Positive+subtractChecked a b = if a Ord.> b then subtract a b else Exception.throw Exception.Underflow++multiply :: Positive -> Positive -> Positive+multiply a b = fromNatural (toNatural a Num.* toNatural b)++addOne :: Positive -> Positive+addOne = fromNatural . (Num.+ 1) . toNatural++subtractOne :: Positive -> Positive+subtractOne = fromNatural . (Num.- 1) . toNatural++subtractOneChecked :: Positive -> Positive+subtractOneChecked x = case x of { 1 -> Exception.throw Exception.Underflow; _ -> subtractOne x }++toIntChecked :: Positive -> Int+toIntChecked = Maybe.fromMaybe (Exception.throw Exception.Overflow) . Bits.toIntegralSized . toNatural++fromInt :: Int -> Positive+fromInt = fromNatural . Num.fromIntegral++fromIntChecked :: Int -> Positive+fromIntChecked x = case Num.signum x of { 1 -> fromInt x; _ -> Exception.throw Exception.Underflow }++enumFrom :: Positive -> [Positive]+enumFrom = List.map fromNatural . Enum.enumFrom . toNatural++enumFromTo :: Positive -> Positive -> [Positive]+enumFromTo a b = List.map fromNatural $ Enum.enumFromTo (toNatural a) (toNatural b)++enumFromThen :: Positive -> Positive -> [Positive]+enumFromThen a b = if a Ord.< b then ascending else descending+ where+ ascending = List.map fromNatural $ Enum.enumFromThen (toNatural a) (toNatural b)+ descending = List.map fromInteger $ List.takeWhile (Ord.>= 1) $+ Enum.enumFromThen (toInteger a) (toInteger b)++enumFromThenTo :: Positive -> Positive -> Positive -> [Positive]+enumFromThenTo a b c = if a Ord.< b then ascending else descending+ where+ ascending = List.map fromNatural $ Enum.enumFromThenTo (toNatural a) (toNatural b) (toNatural c)+ descending = List.map fromInteger $ List.takeWhile (Ord.>= 1) $+ Enum.enumFromThenTo (toInteger a) (toInteger b) (toInteger c)++type Div a = a -> a -> (a, a)++divisionOp :: Div Natural -> Div Positive+divisionOp o a b =+ let (q, r) = o (toNatural a) (toNatural b)+ in (fromNaturalChecked q, fromNaturalChecked r)++instance Num Positive+ where+ abs = id+ negate = \_ -> Exception.throw Exception.Underflow+ signum = \_ -> fromNatural 1+ fromInteger = fromIntegerChecked+ (+) = add+ (*) = multiply+ (-) = subtractChecked++instance Enum Positive+ where+ succ = addOne+ pred = subtractOneChecked++ fromEnum = toIntChecked+ toEnum = fromIntChecked++ enumFrom = enumFrom+ enumFromTo = enumFromTo+ enumFromThen = enumFromThen+ enumFromThenTo = enumFromThenTo++instance Real Positive+ where+ toRational = Num.toRational . toInteger++instance Integral Positive+ where+ toInteger = toInteger+ quotRem = divisionOp Num.quotRem+ divMod = divisionOp Num.divMod++instance Show Positive+ where+ show = Show.show . toNatural+ showsPrec i = Show.showsPrec i . toNatural
test/Spec/Nonempty.hs view
@@ -5,6 +5,7 @@ import Test.Hspec import Data.List.NonEmpty (NonEmpty ((:|)))+import Positive (Positive) import Prelude (String, Integer) spec :: SpecWith ()@@ -34,3 +35,9 @@ describe "reverseList" do it "gets all inputs in reverse" do run reverseList xs `shouldBe` [4, 3, 2, 1]++ describe "sum/product" do+ it "sum works with Positive" do+ run sum [1,2,5] `shouldBe` (8 :: Positive)+ it "product works with Positive" do+ run product [1,2,5] `shouldBe` (10 :: Positive)
test/Spec/ShortcutNonempty.hs view
@@ -4,12 +4,13 @@ import Test.Hspec -import Control.Applicative (pure, (<$>), (<*>))-import Prelude (Integer, undefined)-import Data.List.NonEmpty (NonEmpty ((:|)))-import Data.Maybe (Maybe (Just))+import Control.Applicative (pure, (<$>), (<*>), liftA2) import Data.Bool (Bool (..)) import Data.List ((++))+import Data.List.NonEmpty (NonEmpty ((:|)))+import Data.Maybe (Maybe (Just))+import Positive (Positive)+import Prelude (Integer, undefined) import qualified Data.Char as Char @@ -57,3 +58,9 @@ run or [True,False] `shouldBe` True it "is lazy" do run or (True :| undefined) `shouldBe` True++ describe "sum/product" do+ it "sum works with Positive" do+ run (liftA2 (,) (index 2) sum) [1,2,5,7] `shouldBe` (Just 5, 8 :: Positive)+ it "product works with Positive" do+ run (liftA2 (,) (index 2) product) [1,2,5,3] `shouldBe` (Just 5, 10 :: Positive)