packages feed

integer-types 0.1.1.0 → 0.1.2.0

raw patch · 15 files changed

+850/−682 lines, 15 files

Files

changelog.md view
@@ -1,3 +1,7 @@+## 0.1.2.0 (2023-06-26)++Add `Read` instance for `Positive`+ ## 0.1.1.0 (2023-04-22)  Add `Hashable` instances for `Positive`, `Sign`, and `Signed`
integer-types.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: integer-types-version: 0.1.1.0+version: 0.1.2.0  category: Numeric synopsis: Integer, Natural, and Positive@@ -26,7 +26,9 @@     default-language: GHC2021     ghc-options: -Wall     default-extensions:+        BlockArguments         DerivingStrategies+        LambdaCase         NoImplicitPrelude         PatternSynonyms         ViewPatterns@@ -64,7 +66,7 @@       , exceptions ^>= 0.10.4       , integer-types       , hedgehog ^>= 1.0.5 || ^>= 1.1 || ^>= 1.2-      , hspec ^>= 2.8.5 || ^>= 2.9 || ^>= 2.10+      , hspec ^>= 2.8.5 || ^>= 2.9 || ^>= 2.10 || ^>= 2.11       , hspec-hedgehog ^>= 0.0.1     main-is: Main.hs     other-modules:
library/Integer.hs view
@@ -1,22 +1,45 @@ module Integer-  (-    {- ** Types -} Integer, Natural, Positive,-        Signed (Zero, NonZero, Minus, Plus), Sign (MinusSign, PlusSign),-    {- ** Subtraction -} Subtraction (subtractInteger, subtractSigned), Subtraction' (subtract),-    {- ** Conversion -} IntegerNarrow (narrow), IntegerConvert (convert), IntegerEquiv, yolo, ConvertWithFinite (toInt, fromInt, toWord, fromWord), Finite (..),-    {- ** Lower bound -} BoundedBelow (minBound),+  ( -- ** Types+    Integer,+    Natural,+    Positive,+    Signed (Zero, NonZero, Minus, Plus),+    Sign (MinusSign, PlusSign),++    -- ** Subtraction+    Subtraction (subtractInteger, subtractSigned),+    Subtraction' (subtract),++    -- ** Conversion+    IntegerNarrow (narrow),+    IntegerConvert (convert),+    IntegerEquiv,+    yolo,+    ConvertWithFinite (toInt, fromInt, toWord, fromWord),+    Finite (..),++    -- ** Lower bound+    BoundedBelow (minBound),   )-  where+where  import Integer.BoundedBelow (BoundedBelow (minBound))-import Integer.Conversion (IntegerConvert (convert), IntegerEquiv,-                           IntegerNarrow (narrow), yolo)-import Integer.Finite (ConvertWithFinite (fromInt, fromWord, toInt, toWord),-                       Finite (..))+import Integer.Conversion+  ( IntegerConvert (convert),+    IntegerEquiv,+    IntegerNarrow (narrow),+    yolo,+  )+import Integer.Finite+  ( ConvertWithFinite (fromInt, fromWord, toInt, toWord),+    Finite (..),+  ) import Integer.Integer (Integer) import Integer.Natural (Natural) import Integer.Positive (Positive) import Integer.Sign (Sign (MinusSign, PlusSign)) import Integer.Signed (Signed (Minus, NonZero, Plus, Zero))-import Integer.Subtraction (Subtraction (subtractInteger, subtractSigned),-                            Subtraction' (subtract))+import Integer.Subtraction+  ( Subtraction (subtractInteger, subtractSigned),+    Subtraction' (subtract),+  )
library/Integer/BoundedBelow.hs view
@@ -3,9 +3,7 @@ import Numeric.Natural (Natural)  class BoundedBelow a where-    minBound :: a+  minBound :: a  instance BoundedBelow Natural where-    minBound = 0--+  minBound = 0
library/Integer/Conversion.hs view
@@ -1,84 +1,100 @@ module Integer.Conversion-  (-    IntegerNarrow (narrow),+  ( IntegerNarrow (narrow),     IntegerConvert (convert),     IntegerEquiv,     yolo,   )-  where+where  import Essentials- import Integer.Integer (Integer)+import Integer.Integer qualified as Integer import Integer.Natural (Natural)+import Integer.Natural qualified as Natural import Integer.Positive (Positive)+import Integer.Positive qualified as Positive import Integer.Signed (Signed)--import qualified Integer.Integer as Integer-import qualified Integer.Natural as Natural-import qualified Integer.Positive as Positive-import qualified Integer.Signed as Signed-import qualified Prelude as Num (Integral (..), Num (..))+import Integer.Signed qualified as Signed+import Prelude qualified as Num (Integral (..), Num (..))  class IntegerNarrow a b => IntegerConvert a b where-    convert :: a -> b+  convert :: a -> b  class IntegerNarrow a b where-    narrow :: a -> Maybe b+  narrow :: a -> Maybe b  class (IntegerConvert a b, IntegerConvert b a) => IntegerEquiv a b - ---  Isomorphisms  --- -instance IntegerEquiv   Integer  Integer-instance IntegerConvert Integer  Integer  where convert = id-instance IntegerNarrow  Integer  Integer  where narrow = Just+instance IntegerEquiv Integer Integer -instance IntegerEquiv   Natural  Natural-instance IntegerConvert Natural  Natural  where convert = id-instance IntegerNarrow  Natural  Natural  where narrow  = Just+instance IntegerConvert Integer Integer where convert = id -instance IntegerEquiv   Positive Positive+instance IntegerNarrow Integer Integer where narrow = Just++instance IntegerEquiv Natural Natural++instance IntegerConvert Natural Natural where convert = id++instance IntegerNarrow Natural Natural where narrow = Just++instance IntegerEquiv Positive Positive+ instance IntegerConvert Positive Positive where convert = id-instance IntegerNarrow  Positive Positive where narrow  = Just -instance IntegerEquiv   Signed   Signed-instance IntegerConvert Signed   Signed   where convert = id-instance IntegerNarrow  Signed   Signed   where narrow  = Just+instance IntegerNarrow Positive Positive where narrow = Just -instance IntegerEquiv   Integer  Signed-instance IntegerConvert Integer  Signed   where convert = Integer.toSigned-instance IntegerNarrow  Integer  Signed   where narrow  = Just . convert+instance IntegerEquiv Signed Signed -instance IntegerEquiv   Signed   Integer-instance IntegerConvert Signed   Integer  where convert = Signed.toInteger-instance IntegerNarrow  Signed   Integer  where narrow  = Just . convert+instance IntegerConvert Signed Signed where convert = id +instance IntegerNarrow Signed Signed where narrow = Just +instance IntegerEquiv Integer Signed++instance IntegerConvert Integer Signed where convert = Integer.toSigned++instance IntegerNarrow Integer Signed where narrow = Just . convert++instance IntegerEquiv Signed Integer++instance IntegerConvert Signed Integer where convert = Signed.toInteger++instance IntegerNarrow Signed Integer where narrow = Just . convert+ ---  Prisms  --- -instance IntegerNarrow  Integer  Natural  where narrow  = Integer.toNatural-instance IntegerNarrow  Natural  Integer  where narrow  = Just . convert-instance IntegerConvert Natural  Integer  where convert = Natural.toInteger+instance IntegerNarrow Integer Natural where narrow = Integer.toNatural -instance IntegerNarrow  Signed   Natural  where narrow  = Signed.toNatural-instance IntegerNarrow  Natural  Signed   where narrow  = Just . convert-instance IntegerConvert Natural  Signed   where convert = Natural.toSigned+instance IntegerNarrow Natural Integer where narrow = Just . convert -instance IntegerNarrow  Integer  Positive where narrow  = Integer.toPositive-instance IntegerNarrow  Positive Integer  where narrow  = Just . convert-instance IntegerConvert Positive Integer  where convert = Positive.toInteger+instance IntegerConvert Natural Integer where convert = Natural.toInteger -instance IntegerNarrow  Natural  Positive where narrow  = Natural.toPositive-instance IntegerNarrow  Positive Natural  where narrow  = Just . convert-instance IntegerConvert Positive Natural  where convert = Positive.toNatural+instance IntegerNarrow Signed Natural where narrow = Signed.toNatural -instance IntegerNarrow  Signed   Positive where narrow  = Signed.toPositive-instance IntegerNarrow  Positive Signed   where narrow  = Just . convert-instance IntegerConvert Positive Signed   where convert = Positive.toSigned+instance IntegerNarrow Natural Signed where narrow = Just . convert +instance IntegerConvert Natural Signed where convert = Natural.toSigned +instance IntegerNarrow Integer Positive where narrow = Integer.toPositive++instance IntegerNarrow Positive Integer where narrow = Just . convert++instance IntegerConvert Positive Integer where convert = Positive.toInteger++instance IntegerNarrow Natural Positive where narrow = Natural.toPositive++instance IntegerNarrow Positive Natural where narrow = Just . convert++instance IntegerConvert Positive Natural where convert = Positive.toNatural++instance IntegerNarrow Signed Positive where narrow = Signed.toPositive++instance IntegerNarrow Positive Signed where narrow = Just . convert++instance IntegerConvert Positive Signed where convert = Positive.toSigned+ ---  lol  ---  -- | Partial conversion between 'Num.Integral' types via 'Integer'@@ -86,6 +102,5 @@ -- @ -- yolo = 'Num.fromInteger' . 'Num.toInteger' -- @--- yolo :: (Num.Integral a, Num.Num b) => a -> b yolo = Num.fromInteger . Num.toInteger
library/Integer/Finite.hs view
@@ -1,59 +1,57 @@ module Integer.Finite where -import Essentials- import Data.Int (Int)+import Data.Maybe qualified as Maybe import Data.Word (Word)+import Essentials import Integer.Integer (Integer)+import Integer.Integer qualified as Integer import Integer.Natural (Natural)+import Integer.Natural qualified as Natural import Integer.Positive (Positive)+import Integer.Positive qualified as Positive import Integer.Signed (Signed)+import Integer.Signed qualified as Signed import Prelude (Integral) -import qualified Data.Maybe as Maybe-import qualified Integer.Integer as Integer-import qualified Integer.Natural as Natural-import qualified Integer.Positive as Positive-import qualified Integer.Signed as Signed- class ConvertWithFinite a where-    toWord :: a -> Maybe Word-    fromWord :: Word -> Maybe a-    toInt :: a -> Maybe Int-    fromInt :: Int -> Maybe a+  toWord :: a -> Maybe Word+  fromWord :: Word -> Maybe a+  toInt :: a -> Maybe Int+  fromInt :: Int -> Maybe a  instance ConvertWithFinite Natural where-    toWord = Natural.toWord-    fromWord = Maybe.Just . Natural.fromWord-    toInt = Natural.toInt-    fromInt = Natural.fromInt+  toWord = Natural.toWord+  fromWord = Maybe.Just . Natural.fromWord+  toInt = Natural.toInt+  fromInt = Natural.fromInt  instance ConvertWithFinite Positive where-    toWord = Positive.toWord-    fromWord = Positive.fromWord-    toInt = Positive.toInt-    fromInt = Positive.fromInt+  toWord = Positive.toWord+  fromWord = Positive.fromWord+  toInt = Positive.toInt+  fromInt = Positive.fromInt  instance ConvertWithFinite Integer where-    toWord = Integer.toWord-    fromWord = Maybe.Just . Integer.fromWord-    toInt = Integer.toInt-    fromInt = Maybe.Just . Integer.fromInt+  toWord = Integer.toWord+  fromWord = Maybe.Just . Integer.fromWord+  toInt = Integer.toInt+  fromInt = Maybe.Just . Integer.fromInt  instance ConvertWithFinite Signed where-    toWord = Signed.toWord-    fromWord = Maybe.Just . Signed.fromWord-    toInt = Signed.toInt-    fromInt = Maybe.Just . Signed.fromInt+  toWord = Signed.toWord+  fromWord = Maybe.Just . Signed.fromWord+  toInt = Signed.toInt+  fromInt = Maybe.Just . Signed.fromInt  class (Bounded b, Integral b) => Finite b where-    toFinite :: ConvertWithFinite a => a -> Maybe b-    fromFinite :: ConvertWithFinite a => b -> Maybe a+  toFinite :: ConvertWithFinite a => a -> Maybe b+  fromFinite :: ConvertWithFinite a => b -> Maybe a  instance Finite Int where-    toFinite = toInt-    fromFinite = fromInt+  toFinite = toInt+  fromFinite = fromInt  instance Finite Word where-    toFinite = toWord-    fromFinite = fromWord+  toFinite = toWord+  fromFinite = fromWord
library/Integer/Integer.hs view
@@ -1,31 +1,45 @@ module Integer.Integer-  (-    {- * Type -} Integer,-    {- * Conversion -}-    {- ** Positive -} toPositive, fromPositive,-    {- ** Natural -} toNatural, fromNatural,-    {- ** Signed -} toSigned, fromSigned,-    {- ** Int -} toInt, fromInt,-    {- ** Word -} toWord, fromWord,-  )-  where+  ( -- * Type+    Integer, -import Essentials+    -- * Conversion +    -- ** Positive+    toPositive,+    fromPositive,++    -- ** Natural+    toNatural,+    fromNatural,++    -- ** Signed+    toSigned,+    fromSigned,++    -- ** Int+    toInt,+    fromInt,++    -- ** Word+    toWord,+    fromWord,+  )+where++import Data.Bool qualified as Bool import Data.Int (Int)+import Data.Ord qualified as Ord import Data.Word (Word)+import Essentials+import Integer.Natural qualified as Natural import Integer.Positive (Positive)+import Integer.Positive qualified as Positive import Integer.Signed (Signed (..))+import Integer.Signed qualified as Signed import Numeric.Natural (Natural) import Prelude (Integer)--import qualified Data.Bool as Bool-import qualified Data.Ord as Ord-import qualified Integer.Natural as Natural-import qualified Integer.Positive as Positive-import qualified Integer.Signed as Signed-import qualified Prelude as Bounded (Bounded (..))-import qualified Prelude as Num (Integral (..), Num (..))+import Prelude qualified as Bounded (Bounded (..))+import Prelude qualified as Num (Integral (..), Num (..))  toPositive :: Integer -> Maybe Positive toPositive = Positive.fromInteger@@ -48,8 +62,9 @@ toInt :: Integer -> Maybe Int toInt x = if ok then Just (Num.fromInteger x) else Nothing   where-    ok = x Ord.>= Num.toInteger (Bounded.minBound :: Int) Bool.&&-         x Ord.<= Num.toInteger (Bounded.maxBound :: Int)+    ok =+      x Ord.>= Num.toInteger (Bounded.minBound :: Int)+        Bool.&& x Ord.<= Num.toInteger (Bounded.maxBound :: Int)  fromInt :: Int -> Integer fromInt = Num.toInteger@@ -57,8 +72,9 @@ toWord :: Integer -> Maybe Word toWord x = if ok then Just (Num.fromInteger x) else Nothing   where-    ok = x Ord.>= Num.toInteger (Bounded.minBound :: Word) Bool.&&-         x Ord.<= Num.toInteger (Bounded.maxBound :: Word)+    ok =+      x Ord.>= Num.toInteger (Bounded.minBound :: Word)+        Bool.&& x Ord.<= Num.toInteger (Bounded.maxBound :: Word)  fromWord :: Word -> Integer fromWord = Num.toInteger
library/Integer/Natural.hs view
@@ -1,34 +1,56 @@ module Integer.Natural-  (-    {- * Type -} Natural,-    {- * Subtraction -} subtract,-    {- * Conversion -}-    {- ** Positive -} toPositive, fromPositive,-    {- ** Integer -} toInteger, fromInteger,-    {- ** Signed -} toSigned, fromSigned,-    {- ** Int -} toInt, fromInt,-    {- ** Word -} toWord, fromWord,-    {- * One (1) -} one, addOne, subtractOne,-    {- * List -} length,-  )-  where+  ( -- * Type+    Natural, -import Essentials+    -- * Subtraction+    subtract, +    -- * Conversion++    -- ** Positive+    toPositive,+    fromPositive,++    -- ** Integer+    toInteger,+    fromInteger,++    -- ** Signed+    toSigned,+    fromSigned,++    -- ** Int+    toInt,+    fromInt,++    -- ** Word+    toWord,+    fromWord,++    -- * One (1)+    one,+    addOne,+    subtractOne,++    -- * List+    length,+  )+where+ import Data.Int (Int)+import Data.List qualified as List+import Data.Ord qualified as Ord import Data.Word (Word)+import Essentials+import Integer.Positive qualified as Positive+import Integer.Positive.Unsafe (Positive)+import Integer.Positive.Unsafe qualified as Positive.Unsafe import Integer.Signed (Signed (..))+import Integer.Signed qualified as Signed import Numeric.Natural (Natural)-import Integer.Positive.Unsafe (Positive) import Prelude (Integer)--import qualified Data.List as List-import qualified Data.Ord as Ord-import qualified Integer.Positive as Positive-import qualified Integer.Positive.Unsafe as Positive.Unsafe-import qualified Integer.Signed as Signed-import qualified Prelude as Bounded (Bounded (..))-import qualified Prelude as Num (Integral (..), Num (..))+import Prelude qualified as Bounded (Bounded (..))+import Prelude qualified as Num (Integral (..), Num (..))  toPositive :: Natural -> Maybe Positive toPositive = Positive.fromNatural@@ -71,9 +93,9 @@  subtract :: Natural -> Natural -> Signed subtract a b = case Ord.compare a b of-    Ord.EQ -> Zero-    Ord.GT -> Plus  $ Positive.Unsafe.fromNatural $ (Num.-) a b-    Ord.LT -> Minus $ Positive.Unsafe.fromNatural $ (Num.-) b a+  Ord.EQ -> Zero+  Ord.GT -> Plus $ Positive.Unsafe.fromNatural $ (Num.-) a b+  Ord.LT -> Minus $ Positive.Unsafe.fromNatural $ (Num.-) b a  one :: Natural one = 1@@ -83,8 +105,8 @@  subtractOne :: Natural -> Maybe Signed subtractOne x = case x of-    0 -> Nothing-    p -> Just (subtract p 1)+  0 -> Nothing+  p -> Just (subtract p 1)  length :: [a] -> Natural length = List.foldl' (\x _ -> x Num.+ 1) 0
library/Integer/Positive.hs view
@@ -1,33 +1,55 @@ module Integer.Positive-  (-    {- * Type -} Positive,-    {- * Subtraction -} subtract,-    {- * Conversion -}-    {- ** Natural -} toNatural, fromNatural,-    {- ** Integer -} toInteger, fromInteger,-    {- ** Signed -} toSigned, fromSigned,-    {- ** Int -} toInt, fromInt,-    {- ** Word -} toWord, fromWord,-    {- * One (1) -} one, addOne, subtractOne,-    {- * List -} length,-  )-  where+  ( -- * Type+    Positive, -import Essentials+    -- * Subtraction+    subtract, +    -- * Conversion++    -- ** Natural+    toNatural,+    fromNatural,++    -- ** Integer+    toInteger,+    fromInteger,++    -- ** Signed+    toSigned,+    fromSigned,++    -- ** Int+    toInt,+    fromInt,++    -- ** Word+    toWord,+    fromWord,++    -- * One (1)+    one,+    addOne,+    subtractOne,++    -- * List+    length,+  )+where+ import Data.Int (Int)+import Data.List qualified as List import Data.List.NonEmpty (NonEmpty (..))+import Data.Ord qualified as Ord import Data.Word (Word)+import Essentials import Integer.Positive.Unsafe (Positive, addOne, one, toInteger, toNatural)+import Integer.Positive.Unsafe qualified as Unsafe import Integer.Signed (Signed (..)) import Numeric.Natural (Natural) import Prelude (Integer)--import qualified Data.List as List-import qualified Data.Ord as Ord-import qualified Integer.Positive.Unsafe as Unsafe-import qualified Prelude as Bounded (Bounded (..))-import qualified Prelude as Num (Integral (..), Num (..))+import Prelude qualified as Bounded (Bounded (..))+import Prelude qualified as Num (Integral (..), Num (..))  fromInteger :: Integer -> Maybe Positive fromInteger x = if x Ord.> 0 then Just (Unsafe.fromInteger x) else Nothing@@ -61,9 +83,9 @@  subtract :: Positive -> Positive -> Signed subtract a b = case Ord.compare a b of-    Ord.EQ -> Zero-    Ord.GT -> Plus  $ Unsafe.subtract a b-    Ord.LT -> Minus $ Unsafe.subtract b a+  Ord.EQ -> Zero+  Ord.GT -> Plus $ Unsafe.subtract a b+  Ord.LT -> Minus $ Unsafe.subtract b a  subtractOne :: Positive -> Natural subtractOne x = toNatural x Num.- 1@@ -73,7 +95,7 @@  fromSigned :: Signed -> Maybe Positive fromSigned (Plus x) = Just x-fromSigned _        = Nothing+fromSigned _ = Nothing  length :: NonEmpty a -> Positive length (_ :| xs) = List.foldl' (\x _ -> x Num.+ 1) 1 xs
library/Integer/Positive/Unsafe.hs view
@@ -1,42 +1,66 @@-{- | This module is unsafe not merely in the sense that it contains partial-functions, but moreover than it is capable of constructing the invalid-'Positive' value @'FromNatural' 0@ representing zero, which is not positive.-When a function has "checked" in its name, this indicates that it is partial but-will never construct an invalid 'Positive'. -}-+-- | This module is unsafe not merely in the sense that it contains partial+-- functions, but moreover than it is capable of constructing the invalid+-- 'Positive' value @'FromNatural' 0@ representing zero, which is not positive.+-- When a function has "checked" in its name, this indicates that it is partial but+-- will never construct an invalid 'Positive'. module Integer.Positive.Unsafe-  (-    {- * Type -} Positive (FromNatural),-    {- * Conversion -}-    {- ** Natural -} toNatural, fromNatural, fromNaturalChecked,-    {- ** Integer -} toInteger, fromInteger, fromIntegerChecked,-    {- ** Int -} toInt, fromInt, fromIntChecked,-    {- * Arithmetic -} subtract, subtractChecked,-    {- * One (1) -} one, addOne, subtractOne, subtractOneChecked,-  )-  where+  ( -- * Type+    Positive (FromNatural), -import Essentials ( ($), Enum, Eq, Ord, Show, (.), id )+    -- * Conversion +    -- ** Natural+    toNatural,+    fromNatural,+    fromNaturalChecked,++    -- ** Integer+    toInteger,+    fromInteger,+    fromIntegerChecked,++    -- ** Int+    toInt,+    fromInt,+    fromIntChecked,++    -- * Arithmetic+    subtract,+    subtractChecked,++    -- * One (1)+    one,+    addOne,+    subtractOne,+    subtractOneChecked,+  )+where++import Control.DeepSeq qualified as DeepSeq+import Control.Exception qualified as Exception+import Control.Monad.Fail (fail)+import Data.Bits qualified as Bits import Data.Hashable (Hashable)+import Data.List qualified as List+import Data.Maybe qualified as Maybe+import Data.Ord qualified as Ord+import Essentials import Integer.BoundedBelow (BoundedBelow)+import Integer.BoundedBelow qualified as BoundedBelow import Numeric.Natural (Natural)-import Prelude (Int, Integer, Integral, Num, Real)--import qualified Control.DeepSeq as DeepSeq-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 Integer.BoundedBelow as BoundedBelow-import qualified Prelude as Enum (Enum (..))-import qualified Prelude as Num (Integral (..), Num (..), Real (..),-                                 fromIntegral)-import qualified Text.Show as Show+import Text.Read qualified as Read+import Text.Show qualified as Show+import Prelude (Int, Integer, Integral, Num, Read, Real)+import Prelude qualified as Enum (Enum (..))+import Prelude qualified as Num+  ( Integral (..),+    Num (..),+    Real (..),+    fromIntegral,+  ) -newtype Positive = FromNatural{ toNatural :: Natural }-    deriving newtype (Eq, Ord, Hashable)+newtype Positive = FromNatural {toNatural :: Natural}+  deriving newtype (Eq, Ord, Hashable)  instance DeepSeq.NFData Positive where rnf (FromNatural x) = DeepSeq.rnf x @@ -77,7 +101,7 @@ subtractOne = fromNatural . (Num.- 1) . toNatural  subtractOneChecked :: Positive -> Positive-subtractOneChecked x = case x of { 1 -> Exception.throw Exception.Underflow; _ -> subtractOne x }+subtractOneChecked x = case x of 1 -> Exception.throw Exception.Underflow; _ -> subtractOne x  toInt :: Positive -> Int toInt = Num.fromIntegral . toNatural@@ -89,7 +113,7 @@ fromInt = fromNatural . Num.fromIntegral  fromIntChecked :: Int -> Positive-fromIntChecked x = case Num.signum x of { 1 -> fromInt x; _ -> Exception.throw Exception.Underflow }+fromIntChecked x = case Num.signum x of 1 -> fromInt x; _ -> Exception.throw Exception.Underflow  enumFrom :: Positive -> [Positive] enumFrom = List.map fromNatural . Enum.enumFrom . toNatural@@ -101,61 +125,69 @@ 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)+    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)+    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)+  let (q, r) = o (toNatural a) (toNatural b)+   in (fromNaturalChecked q, fromNaturalChecked r) -instance BoundedBelow Positive-  where-    minBound = 1+instance BoundedBelow Positive where+  minBound = 1 -instance Num Positive-  where-    abs = id-    negate = \_ -> Exception.throw Exception.Underflow-    signum = \_ -> fromNatural 1-    fromInteger = fromIntegerChecked-    (+) = add-    (*) = multiply-    (-) = subtractChecked+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+instance Enum Positive where+  succ = addOne+  pred = subtractOneChecked -    fromEnum = toIntChecked-    toEnum = fromIntChecked+  fromEnum = toIntChecked+  toEnum = fromIntChecked -    enumFrom = enumFrom-    enumFromTo = enumFromTo-    enumFromThen = enumFromThen-    enumFromThenTo = enumFromThenTo+  enumFrom = enumFrom+  enumFromTo = enumFromTo+  enumFromThen = enumFromThen+  enumFromThenTo = enumFromThenTo -instance Real Positive-  where-    toRational = Num.toRational . toInteger+instance Real Positive where+  toRational = Num.toRational . toInteger -instance Integral Positive-  where-    toInteger = toInteger-    quotRem = divisionOp Num.quotRem-    divMod = divisionOp Num.divMod+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+instance Show Positive where+  show = Show.show . toNatural+  showsPrec i = Show.showsPrec i . toNatural++instance Read Positive where+  readsPrec i = do+    xs <- Read.readsPrec @Natural i+    pure $ xs & Maybe.mapMaybe \case+      (0, _) -> Nothing+      (n, s) -> Just (fromNatural n, s)+  readPrec = do+    n <- Read.readPrec @Natural+    if n == 0 then fail "0" else pure $ fromNatural n
library/Integer/Sign.hs view
@@ -1,28 +1,29 @@ module Integer.Sign-  (-    {- * Type -} Sign (..),-    {- * Operations -} negate, multiply,+  ( -- * Type+    Sign (..),++    -- * Operations+    negate,+    multiply,   )-  where+where +import Control.DeepSeq qualified as DeepSeq+import Data.Hashable (Hashable (hashWithSalt)) import Essentials- import Prelude (seq)-import qualified Prelude as Enum (Enum (..))-import Data.Hashable (Hashable (hashWithSalt))--import qualified Control.DeepSeq as DeepSeq+import Prelude qualified as Enum (Enum (..))  data Sign = MinusSign | PlusSign-    deriving stock (Eq, Ord, Show, Enum, Bounded)+  deriving stock (Eq, Ord, Show, Enum, Bounded)  instance DeepSeq.NFData Sign where rnf x = seq x ()  instance Hashable Sign where-    hashWithSalt salt x = salt `hashWithSalt` (Enum.fromEnum x)+  hashWithSalt salt x = salt `hashWithSalt` (Enum.fromEnum x)  negate :: Sign -> Sign-negate PlusSign  = MinusSign+negate PlusSign = MinusSign negate MinusSign = PlusSign  multiply :: Sign -> Sign -> Sign
library/Integer/Signed.hs view
@@ -1,87 +1,103 @@ module Integer.Signed-  (-    {- * Type -} Signed (Zero, NonZero, Plus, Minus, NotPlus, NotMinus),-    {- * Conversion -}-    {- ** Integer -} toInteger, fromInteger,-    {- ** Natural -} toNatural, fromNatural,-    {- ** Positive -} toPositive, fromPositive,-    {- ** Int -} toInt, fromInt,-    {- ** Word -} toWord, fromWord,-  )-  where+  ( -- * Type+    Signed (Zero, NonZero, Plus, Minus, NotPlus, NotMinus), -import Essentials+    -- * Conversion +    -- ** Integer+    toInteger,+    fromInteger,++    -- ** Natural+    toNatural,+    fromNatural,++    -- ** Positive+    toPositive,+    fromPositive,++    -- ** Int+    toInt,+    fromInt,++    -- ** Word+    toWord,+    fromWord,+  )+where++import Control.DeepSeq qualified as DeepSeq import Data.Hashable (Hashable (hashWithSalt)) import Data.Int (Int)+import Data.List qualified as List+import Data.Ord qualified as Ord import Data.Word (Word)+import Essentials import Integer.Positive.Unsafe (Positive)+import Integer.Positive.Unsafe qualified as Positive.Unsafe import Integer.Sign (Sign (..))+import Integer.Sign qualified as Sign import Numeric.Natural (Natural)+import Text.Show qualified as Show import Prelude (Integer, Integral, Num, Real, seq)--import qualified Control.DeepSeq as DeepSeq-import qualified Data.List as List-import qualified Data.Ord as Ord-import qualified Integer.Positive.Unsafe as Positive.Unsafe-import qualified Integer.Sign as Sign-import qualified Prelude as Bounded (Bounded (..))-import qualified Prelude as Enum (Enum (..))-import qualified Prelude as Num (Integral (..), Num (..), Real (..))-import qualified Text.Show as Show+import Prelude qualified as Bounded (Bounded (..))+import Prelude qualified as Enum (Enum (..))+import Prelude qualified as Num (Integral (..), Num (..), Real (..))  data Signed = Zero | NonZero Sign Positive-    deriving stock (Eq)+  deriving stock (Eq)  instance Ord Signed where-    compare Zero Zero = Ord.EQ--    compare Zero (Minus _) = Ord.GT-    compare Zero (Plus _ ) = Ord.LT-    compare (Minus _) Zero = Ord.LT-    compare (Plus  _) Zero = Ord.GT--    compare (Plus  _) (Minus _) = Ord.GT-    compare (Minus _) (Plus  _) = Ord.LT-    compare (Plus  a) (Plus  b) = Ord.compare a b-    compare (Minus a) (Minus b) = Ord.compare b a+  compare Zero Zero = Ord.EQ+  compare Zero (Minus _) = Ord.GT+  compare Zero (Plus _) = Ord.LT+  compare (Minus _) Zero = Ord.LT+  compare (Plus _) Zero = Ord.GT+  compare (Plus _) (Minus _) = Ord.GT+  compare (Minus _) (Plus _) = Ord.LT+  compare (Plus a) (Plus b) = Ord.compare a b+  compare (Minus a) (Minus b) = Ord.compare b a  instance DeepSeq.NFData Signed where-    rnf Zero          = ()-    rnf (NonZero a b) = a `seq` b `seq` ()+  rnf Zero = ()+  rnf (NonZero a b) = a `seq` b `seq` ()  instance Hashable Signed where-    hashWithSalt s Zero      = s `hashWithSalt` ( 0 :: Int)-    hashWithSalt s (Plus  x) = s `hashWithSalt` ( 1 :: Int) `hashWithSalt` x-    hashWithSalt s (Minus x) = s `hashWithSalt` (-1 :: Int) `hashWithSalt` x+  hashWithSalt s Zero = s `hashWithSalt` (0 :: Int)+  hashWithSalt s (Plus x) = s `hashWithSalt` (1 :: Int) `hashWithSalt` x+  hashWithSalt s (Minus x) = s `hashWithSalt` (-1 :: Int) `hashWithSalt` x  pattern Minus :: Positive -> Signed pattern Minus x = NonZero MinusSign x-pattern Plus :: Positive -> Signed +pattern Plus :: Positive -> Signed pattern Plus x = NonZero PlusSign x  -- | A 'Signed' that is either zero or positive pattern NotMinus :: Natural -> Signed pattern NotMinus x <- (toNatural -> Just x)-  where NotMinus = fromNatural+  where+    NotMinus = fromNatural  -- | A 'Signed' that is either zero or negative; -- the 'Natural' gives the magnitude of the negative pattern NotPlus :: Natural -> Signed pattern NotPlus x <- ((toNatural . negate) -> Just x)-  where NotPlus = negate . fromNatural+  where+    NotPlus = negate . fromNatural -{-# complete Zero, Minus, Plus #-}-{-# complete Plus, NotPlus #-}-{-# complete Minus, NotMinus #-}+{-# COMPLETE Zero, Minus, Plus #-} +{-# COMPLETE Plus, NotPlus #-}++{-# COMPLETE Minus, NotMinus #-}+ fromPositive :: Positive -> Signed fromPositive = Plus  toPositive :: Signed -> Maybe Positive toPositive (Plus x) = Just x-toPositive _        = Nothing+toPositive _ = Nothing  fromNatural :: Natural -> Signed fromNatural 0 = Zero@@ -89,129 +105,122 @@  toNatural :: Signed -> Maybe Natural toNatural (Minus _) = Nothing-toNatural Zero      = Just 0-toNatural (Plus x)  = Just (Positive.Unsafe.toNatural x)+toNatural Zero = Just 0+toNatural (Plus x) = Just (Positive.Unsafe.toNatural x)  add :: Signed -> Signed -> Signed add Zero x = x add x Zero = x add (NonZero sa a) (NonZero sb b) = case (sa, sb) of-    (PlusSign, PlusSign)   -> Plus  $ a Num.+ b-    (MinusSign, MinusSign) -> Minus $ a Num.+ b--    (MinusSign, PlusSign) -> case Ord.compare a b of-        Ord.EQ -> Zero-        Ord.LT -> Plus  $ Positive.Unsafe.subtract b a-        Ord.GT -> Minus $ Positive.Unsafe.subtract a b--    (PlusSign, MinusSign) -> case Ord.compare a b of-        Ord.EQ -> Zero-        Ord.LT -> Minus $ Positive.Unsafe.subtract b a-        Ord.GT -> Plus  $ Positive.Unsafe.subtract a b+  (PlusSign, PlusSign) -> Plus $ a Num.+ b+  (MinusSign, MinusSign) -> Minus $ a Num.+ b+  (MinusSign, PlusSign) -> case Ord.compare a b of+    Ord.EQ -> Zero+    Ord.LT -> Plus $ Positive.Unsafe.subtract b a+    Ord.GT -> Minus $ Positive.Unsafe.subtract a b+  (PlusSign, MinusSign) -> case Ord.compare a b of+    Ord.EQ -> Zero+    Ord.LT -> Minus $ Positive.Unsafe.subtract b a+    Ord.GT -> Plus $ Positive.Unsafe.subtract a b  negate :: Signed -> Signed-negate Zero          = Zero+negate Zero = Zero negate (NonZero s x) = NonZero (Sign.negate s) x  multiply :: Signed -> Signed -> Signed multiply Zero _ = Zero multiply _ Zero = Zero multiply (NonZero sa a) (NonZero sb b) =-    NonZero (Sign.multiply sa sb) (a Num.* b)+  NonZero (Sign.multiply sa sb) (a Num.* b)  abs :: Signed -> Signed abs Zero = Zero abs x@(NonZero s p) = case s of-    PlusSign  -> x-    MinusSign -> NonZero PlusSign p+  PlusSign -> x+  MinusSign -> NonZero PlusSign p  signum :: Signed -> Signed-signum Zero          = Zero+signum Zero = Zero signum (NonZero s _) = NonZero s Positive.Unsafe.one  fromInteger :: Integer -> Signed fromInteger x = case Ord.compare x 0 of-    Ord.EQ -> Zero-    Ord.LT -> Minus $ Positive.Unsafe.fromInteger $ Num.abs x-    Ord.GT -> Plus  $ Positive.Unsafe.fromInteger x+  Ord.EQ -> Zero+  Ord.LT -> Minus $ Positive.Unsafe.fromInteger $ Num.abs x+  Ord.GT -> Plus $ Positive.Unsafe.fromInteger x  toInteger :: Signed -> Integer-toInteger Zero      = 0-toInteger (Plus x)  = Positive.Unsafe.toInteger x+toInteger Zero = 0+toInteger (Plus x) = Positive.Unsafe.toInteger x toInteger (Minus x) = Num.negate $ Positive.Unsafe.toInteger x  toInt :: Signed -> Maybe Int toInt x = case x of-    Zero -> Just 0-    Plus p -> if ok then Just (Num.fromInteger i) else Nothing-      where-        ok = i Ord.<= Num.toInteger (Bounded.maxBound :: Int)-        i = Positive.Unsafe.toInteger p-    Minus p -> if ok then Just (Num.fromInteger i) else Nothing-      where-        ok = i Ord.>= Num.toInteger (Bounded.minBound :: Int)-        i = Num.negate (Positive.Unsafe.toInteger p)+  Zero -> Just 0+  Plus p -> if ok then Just (Num.fromInteger i) else Nothing+    where+      ok = i Ord.<= Num.toInteger (Bounded.maxBound :: Int)+      i = Positive.Unsafe.toInteger p+  Minus p -> if ok then Just (Num.fromInteger i) else Nothing+    where+      ok = i Ord.>= Num.toInteger (Bounded.minBound :: Int)+      i = Num.negate (Positive.Unsafe.toInteger p)  fromInt :: Int -> Signed fromInt x = case Ord.compare x 0 of-    Ord.EQ -> Zero-    Ord.GT -> Plus $ Positive.Unsafe.fromInt x-    Ord.LT -> Minus $ Positive.Unsafe.fromInteger $ Num.negate $ Num.toInteger x+  Ord.EQ -> Zero+  Ord.GT -> Plus $ Positive.Unsafe.fromInt x+  Ord.LT -> Minus $ Positive.Unsafe.fromInteger $ Num.negate $ Num.toInteger x  toWord :: Signed -> Maybe Word toWord x = case x of-    Zero -> Just 0-    Plus p -> if ok then Just (Num.fromInteger i) else Nothing-      where-        ok = i Ord.<= Num.toInteger (Bounded.maxBound :: Word)-        i = Positive.Unsafe.toInteger p-    Minus _ -> Nothing+  Zero -> Just 0+  Plus p -> if ok then Just (Num.fromInteger i) else Nothing+    where+      ok = i Ord.<= Num.toInteger (Bounded.maxBound :: Word)+      i = Positive.Unsafe.toInteger p+  Minus _ -> Nothing  fromWord :: Word -> Signed fromWord x = case x of-    0 -> Zero-    _ -> Plus $ Positive.Unsafe.fromInteger (Num.toInteger x)+  0 -> Zero+  _ -> Plus $ Positive.Unsafe.fromInteger (Num.toInteger x)  type Div a = a -> a -> (a, a)  divisionOp :: Div Integer -> Div Signed divisionOp o a b =-    let (q, r) = o (toInteger a) (toInteger b)-    in (fromInteger q, fromInteger r)+  let (q, r) = o (toInteger a) (toInteger b)+   in (fromInteger q, fromInteger r) -instance Num Signed-  where-    (+) = add-    (*) = multiply-    negate = negate-    abs = abs-    signum = signum-    fromInteger = fromInteger+instance Num Signed where+  (+) = add+  (*) = multiply+  negate = negate+  abs = abs+  signum = signum+  fromInteger = fromInteger -instance Enum Signed-  where-    pred = fromInteger . Enum.pred . toInteger-    succ = fromInteger . Enum.succ . toInteger+instance Enum Signed where+  pred = fromInteger . Enum.pred . toInteger+  succ = fromInteger . Enum.succ . toInteger -    toEnum = fromInteger . Enum.toEnum-    fromEnum = Enum.fromEnum . toInteger+  toEnum = fromInteger . Enum.toEnum+  fromEnum = Enum.fromEnum . toInteger -    enumFrom a = List.map fromInteger $ Enum.enumFrom (toInteger a)-    enumFromTo a b = List.map fromInteger $ Enum.enumFromTo (toInteger a) (toInteger b)-    enumFromThen a b = List.map fromInteger $ Enum.enumFromThen (toInteger a) (toInteger b)-    enumFromThenTo a b c = List.map fromInteger $ Enum.enumFromThenTo (toInteger a) (toInteger b) (toInteger c)+  enumFrom a = List.map fromInteger $ Enum.enumFrom (toInteger a)+  enumFromTo a b = List.map fromInteger $ Enum.enumFromTo (toInteger a) (toInteger b)+  enumFromThen a b = List.map fromInteger $ Enum.enumFromThen (toInteger a) (toInteger b)+  enumFromThenTo a b c = List.map fromInteger $ Enum.enumFromThenTo (toInteger a) (toInteger b) (toInteger c) -instance Real Signed-  where-    toRational = Num.toRational . toInteger+instance Real Signed where+  toRational = Num.toRational . toInteger -instance Integral Signed-  where-    toInteger = toInteger-    quotRem = divisionOp Num.quotRem-    divMod = divisionOp Num.divMod+instance Integral Signed where+  toInteger = toInteger+  quotRem = divisionOp Num.quotRem+  divMod = divisionOp Num.divMod -instance Show Signed-  where-    show = Show.show . Num.toInteger-    showsPrec i = Show.showsPrec i . Num.toInteger+instance Show Signed where+  show = Show.show . Num.toInteger+  showsPrec i = Show.showsPrec i . Num.toInteger
library/Integer/Subtraction.hs view
@@ -1,47 +1,45 @@ module Integer.Subtraction-  (-    Subtraction (subtractInteger, subtractSigned),+  ( Subtraction (subtractInteger, subtractSigned),     Subtraction' (subtract),   )-  where+where  import Integer.Integer (Integer) import Integer.Natural (Natural)+import Integer.Natural qualified as Natural import Integer.Positive (Positive)+import Integer.Positive qualified as Positive import Integer.Signed (Signed)--import qualified Integer.Natural as Natural-import qualified Integer.Positive as Positive-import qualified Integer.Signed as Signed-import qualified Prelude as Num (Num (..))+import Integer.Signed qualified as Signed+import Prelude qualified as Num (Num (..))  -- | Domain of a subtraction operation class Subtraction a where-    subtractInteger :: a -> a -> Integer-    subtractInteger a b = Signed.toInteger (subtractSigned a b)+  subtractInteger :: a -> a -> Integer+  subtractInteger a b = Signed.toInteger (subtractSigned a b) -    subtractSigned  :: a -> a -> Signed-    subtractSigned a b = Signed.fromInteger (subtractInteger a b)+  subtractSigned :: a -> a -> Signed+  subtractSigned a b = Signed.fromInteger (subtractInteger a b)  instance Subtraction Integer where-    subtractInteger = (Num.-)+  subtractInteger = (Num.-)  instance Subtraction Signed where-    subtractInteger a b = (Num.-) (Signed.toInteger a) (Signed.toInteger b)-    subtractSigned = (Num.-)+  subtractInteger a b = (Num.-) (Signed.toInteger a) (Signed.toInteger b)+  subtractSigned = (Num.-)  instance Subtraction Natural where-    subtractSigned = Natural.subtract+  subtractSigned = Natural.subtract  instance Subtraction Positive where-    subtractSigned = Positive.subtract+  subtractSigned = Positive.subtract  -- | Codomain of a subtraction operation class Subtraction' b where-    subtract :: Subtraction a => a -> a -> b+  subtract :: Subtraction a => a -> a -> b  instance Subtraction' Integer where-    subtract = subtractInteger+  subtract = subtractInteger  instance Subtraction' Signed where-    subtract = subtractSigned+  subtract = subtractSigned
test/Integer/Gen.hs view
@@ -1,55 +1,60 @@ module Integer.Gen-  (-    GenIntegral (integral),+  ( GenIntegral (integral),     GenFinite (finite),     astronomical,   )-  where--import Essentials+where  import Data.Int (Int) import Data.Word (Word)-import Integer (BoundedBelow (..), Integer, Natural, Positive, Sign (..),-                Signed (..))--import qualified Hedgehog-import qualified Hedgehog.Gen as Gen-import qualified Hedgehog.Range as Range-import qualified Prelude as Bounded (Bounded (..))-import qualified Prelude as Num (Integral (..), Num (..), (+), (^))+import Essentials+import Hedgehog qualified+import Hedgehog.Gen qualified as Gen+import Hedgehog.Range qualified as Range+import Integer+  ( BoundedBelow (..),+    Integer,+    Natural,+    Positive,+    Sign (..),+    Signed (..),+  )+import Prelude qualified as Bounded (Bounded (..))+import Prelude qualified as Num (Integral (..), Num (..), (+), (^))  --- -class (Num.Integral a, Show a) => GenIntegral a-  where-    -- | Generators for 'Integer', 'Natural', 'Positive',-    -- or 'Signed' selected from one of three methods:-    ---    -- * small numbers (magnitude less than ten)-    -- * large numbers (well in excess of 64-bit)-    -- * numbers at or around a bound of 'Int' or 'Word'-    integral :: Hedgehog.Gen a+class (Num.Integral a, Show a) => GenIntegral a where+  -- | Generators for 'Integer', 'Natural', 'Positive',+  -- or 'Signed' selected from one of three methods:+  --+  -- * small numbers (magnitude less than ten)+  -- * large numbers (well in excess of 64-bit)+  -- * numbers at or around a bound of 'Int' or 'Word'+  integral :: Hedgehog.Gen a -instance GenIntegral Integer  where integral = integer-instance GenIntegral Natural  where integral = boundedBelow+instance GenIntegral Integer where integral = integer++instance GenIntegral Natural where integral = boundedBelow+ instance GenIntegral Positive where integral = boundedBelow-instance GenIntegral Signed   where integral = signed +instance GenIntegral Signed where integral = signed+ --- -class (Num.Integral a, Bounded.Bounded a, Show a) => GenFinite a-  where-    finite :: Hedgehog.Gen a+class (Num.Integral a, Bounded.Bounded a, Show a) => GenFinite a where+  finite :: Hedgehog.Gen a  instance GenFinite Int where finite = defaultFinite  instance GenFinite Word where finite = defaultFinite  defaultFinite :: (Num.Integral a, Bounded.Bounded a) => Hedgehog.Gen a-defaultFinite = Gen.choice-    [ Gen.integral $ Range.linear Bounded.minBound Bounded.maxBound-    , Gen.integral $ Range.linear Bounded.maxBound Bounded.minBound+defaultFinite =+  Gen.choice+    [ Gen.integral $ Range.linear Bounded.minBound Bounded.maxBound,+      Gen.integral $ Range.linear Bounded.maxBound Bounded.minBound     ]  ---@@ -89,13 +94,14 @@ bigBoundedBelow = fmap Num.fromInteger $ Gen.integral bigRange  nearPositiveFiniteBound :: forall a. Num.Integral a => Hedgehog.Gen a-nearPositiveFiniteBound = fmap Num.fromInteger $+nearPositiveFiniteBound =+  fmap Num.fromInteger $     pure (Num.+)-    <*> Gen.element-      [ Num.toInteger (Bounded.maxBound :: Int)-      , Num.toInteger (Bounded.maxBound :: Word)-      ]-    <*> smolInteger+      <*> Gen.element+        [ Num.toInteger (Bounded.maxBound :: Int),+          Num.toInteger (Bounded.maxBound :: Word)+        ]+      <*> smolInteger  --- @@ -103,9 +109,10 @@ signed = Gen.choice [smolSigned, nearFiniteBoundSigned, bigSigned]  smolSigned :: Hedgehog.Gen Signed-smolSigned = Gen.frequency-    [ (,) 1 $ pure Zero-    , (,) 9 $ pure NonZero <*> sign <*> smolBoundedBelow+smolSigned =+  Gen.frequency+    [ (,) 1 $ pure Zero,+      (,) 9 $ pure NonZero <*> sign <*> smolBoundedBelow     ]  bigSigned :: Hedgehog.Gen Signed
test/Main.hs view
@@ -1,282 +1,303 @@ module Main (main) where -import Integer--import Essentials--import Test.Hspec (hspec, describe, it, shouldBe)-import Test.Hspec.Hedgehog-    ((===), evalMaybe, modifyMaxSuccess, hedgehog)- import Control.DeepSeq (NFData, ($!!)) import Control.Exception (Exception, throw)+import Control.Exception qualified as Exception (ArithException (Underflow))+import Control.Monad.Catch qualified as Exception (MonadCatch, try)+import Data.Bool qualified as Bool import Data.Either (Either (..))+import Data.Either qualified as Either import Data.Int (Int) import Data.List (take) import Data.List.NonEmpty (NonEmpty ((:|)))+import Data.Ord qualified as Ord import Data.Word (Word)-import Integer.Gen (GenFinite)-import Integer.Gen (GenIntegral)-import Prelude (Num, fromInteger, toInteger, ($!), (*), (+), (-))+import Essentials+import Hedgehog qualified+import Integer+import Integer.Gen (GenFinite, GenIntegral)+import Integer.Gen qualified as Gen+import Integer.Natural qualified as Natural+import Integer.Positive qualified as Positive import System.IO (IO)--import qualified Control.Exception as Exception (ArithException (Underflow))-import qualified Control.Monad.Catch as Exception (MonadCatch, try)-import qualified Data.Bool as Bool-import qualified Data.Either as Either-import qualified Data.Ord as Ord-import qualified Hedgehog-import qualified Integer.Gen as Gen-import qualified Integer.Natural as Natural-import qualified Integer.Positive as Positive-import qualified Prelude as Bounded (Bounded (..))-import qualified Prelude as Num (fromInteger)-import qualified Prelude as Num (toInteger)+import Test.Hspec (describe, hspec, it, shouldBe)+import Test.Hspec.Hedgehog+  ( evalMaybe,+    hedgehog,+    modifyMaxSuccess,+    (===),+  )+import Prelude (Num, fromInteger, toInteger, ($!), (*), (+), (-))+import Prelude qualified as Bounded (Bounded (..))+import Prelude qualified as Num (fromInteger, toInteger)  main :: IO () main = hspec do--    describe "Closed Num operations op behaves the same in A \-             \as in Integer" $ modifyMaxSuccess (\_ -> 1000) do--        let check :: forall a m. GenIntegral a => Monad m =>-                (forall b. Num b => b -> b -> b) -> Hedgehog.PropertyT m ()-            check o = do-                x :: a <- Hedgehog.forAll Gen.integral-                y :: a <- Hedgehog.forAll Gen.integral-                x `o` y === fromInteger (toInteger x `o` toInteger y)--        it "op = (+), A = Positive" $ hedgehog $ check @Positive (+)-        it "op = (+), A = Signed"   $ hedgehog $ check @Signed   (+)-        it "op = (*), A = Positive" $ hedgehog $ check @Positive (*)-        it "op = (*), A = Signed"   $ hedgehog $ check @Signed   (*)--    describe "subtract in A behaves the same as \-             \(-) in B" $ modifyMaxSuccess (\_ -> 1000) do--        let check :: forall a b m.-                (GenIntegral a, Subtraction a, Subtraction' b, Num b) =>-                (IntegerConvert a b, IntegerNarrow b a) =>-                (Eq b, Show b) =>-                Exception.MonadCatch m => Hedgehog.PropertyT m ()-            check = do-                x :: a <- Hedgehog.forAll Gen.integral-                y :: a <- Hedgehog.forAll Gen.integral-                (subtract x y :: b) === (convert x - convert y :: b)--        it "A = Natural,  B = Signed"  $ hedgehog $ check @Natural  @Signed-        it "A = Natural,  B = Integer" $ hedgehog $ check @Natural  @Integer-        it "A = Positive, B = Signed"  $ hedgehog $ check @Positive @Signed-        it "A = Positive, B = Integer" $ hedgehog $ check @Positive @Integer--    describe "(-) in A behaves the same as (-) in Integer if the result \-             \is in A, undefined otherwise" $ modifyMaxSuccess (\_ -> 1000) do--        let check :: forall a m.-                (GenIntegral a, Subtraction a, IntegerNarrow Integer a) =>-                Exception.MonadCatch m => Hedgehog.PropertyT m ()-            check = do-                x :: a <- Hedgehog.forAll Gen.integral-                y :: a <- Hedgehog.forAll Gen.integral-                case narrow (toInteger x - toInteger y) :: Maybe a of-                    Just z -> x - y === z-                    Nothing -> do-                        z <- Exception.try (pure $! x - y)-                        z === Either.Left Exception.Underflow--        it "A = Positive" $ hedgehog $ check @Positive--    describe "convert (convert x) = x" do--        let check :: forall a b m. (GenIntegral a, IntegerEquiv a b) =>-                Monad m => Hedgehog.PropertyT m ()-            check = do-                x :: a <- Hedgehog.forAll Gen.integral-                convert (convert x :: b) === x+  describe+    "Closed Num operations op behaves the same in A \+    \as in Integer"+    $ modifyMaxSuccess (\_ -> 1000) do+      let check ::+            forall a m.+            GenIntegral a =>+            Monad m =>+            (forall b. Num b => b -> b -> b) ->+            Hedgehog.PropertyT m ()+          check o = do+            x :: a <- Hedgehog.forAll Gen.integral+            y :: a <- Hedgehog.forAll Gen.integral+            x `o` y === fromInteger (toInteger x `o` toInteger y) -        it "A = Integer, B = Signed"  $ hedgehog $ check @Integer @Signed-        it "A = Signed,  B = Integer" $ hedgehog $ check @Signed @Integer+      it "op = (+), A = Positive" $ hedgehog $ check @Positive (+)+      it "op = (+), A = Signed" $ hedgehog $ check @Signed (+)+      it "op = (*), A = Positive" $ hedgehog $ check @Positive (*)+      it "op = (*), A = Signed" $ hedgehog $ check @Signed (*) -    describe "narrow (convert x) = Just x" $ modifyMaxSuccess (\_ -> 1000) do+  describe+    "subtract in A behaves the same as (-) in B"+    $ modifyMaxSuccess (\_ -> 1000) do+      let check ::+            forall a b m.+            (GenIntegral a, Subtraction a, Subtraction' b, Num b) =>+            (IntegerConvert a b, IntegerNarrow b a) =>+            (Eq b, Show b) =>+            Exception.MonadCatch m =>+            Hedgehog.PropertyT m ()+          check = do+            x :: a <- Hedgehog.forAll Gen.integral+            y :: a <- Hedgehog.forAll Gen.integral+            (subtract x y :: b) === (convert x - convert y :: b) -        let check :: forall a b m.-                (GenIntegral a, IntegerConvert a b, IntegerNarrow b a) =>-                Monad m => Hedgehog.PropertyT m ()-            check = do-                x :: a <- Hedgehog.forAll Gen.integral-                narrow (convert x :: b) === Just x+      it "A = Natural,  B = Signed" $ hedgehog $ check @Natural @Signed+      it "A = Natural,  B = Integer" $ hedgehog $ check @Natural @Integer+      it "A = Positive, B = Signed" $ hedgehog $ check @Positive @Signed+      it "A = Positive, B = Integer" $ hedgehog $ check @Positive @Integer -        it "A = Natural,  B = Integer" $ hedgehog $ check @Natural  @Integer-        it "A = Natural,  B = Signed"  $ hedgehog $ check @Natural  @Signed-        it "A = Positive, B = Integer" $ hedgehog $ check @Positive @Integer-        it "A = Positive, B = Signed"  $ hedgehog $ check @Positive @Signed-        it "A = Positive, B = Natural" $ hedgehog $ check @Positive @Natural+  describe+    "(-) in A behaves the same as (-) in Integer if the result \+    \is in A, undefined otherwise"+    $ modifyMaxSuccess (\_ -> 1000) do+      let check ::+            forall a m.+            (GenIntegral a, Subtraction a, IntegerNarrow Integer a) =>+            Exception.MonadCatch m =>+            Hedgehog.PropertyT m ()+          check = do+            x :: a <- Hedgehog.forAll Gen.integral+            y :: a <- Hedgehog.forAll Gen.integral+            case narrow (toInteger x - toInteger y) :: Maybe a of+              Just z -> x - y === z+              Nothing -> do+                z <- Exception.try (pure $! x - y)+                z === Either.Left Exception.Underflow -    describe "narrow x = (Just y | convert y = x) \-             \or Nothing" $ modifyMaxSuccess (\_ -> 1000) do+      it "A = Positive" $ hedgehog $ check @Positive -        let check :: forall a b m. (GenIntegral a, BoundedBelow b) =>-                (IntegerConvert b a, IntegerNarrow a b) =>-                (Show b, Eq b) => Monad m => Hedgehog.PropertyT m ()-            check = do-                x :: a <- Hedgehog.forAll Gen.integral-                let y :: Maybe b = narrow x-                if x Ord.>= convert (minBound @b)-                  then do-                      z <- evalMaybe y-                      convert z === x-                  else y === Nothing+  describe "convert (convert x) = x" do+    let check ::+          forall a b m.+          (GenIntegral a, IntegerEquiv a b) =>+          Monad m =>+          Hedgehog.PropertyT m ()+        check = do+          x :: a <- Hedgehog.forAll Gen.integral+          convert (convert x :: b) === x -        it "A = Integer, B = Natural"  $ hedgehog $ check @Integer @Natural-        it "A = Signed,  B = Natural"  $ hedgehog $ check @Signed  @Natural-        it "A = Integer, B = Positive" $ hedgehog $ check @Integer @Positive-        it "A = Signed,  B = Positive" $ hedgehog $ check @Signed  @Positive-        it "A = Natural, B = Positive" $ hedgehog $ check @Natural @Positive+    it "A = Integer, B = Signed" $ hedgehog $ check @Integer @Signed+    it "A = Signed,  B = Integer" $ hedgehog $ check @Signed @Integer -    describe "yolo (yolo x) = x, if Integer x is in range of A" do+  describe "narrow (convert x) = Just x" $ modifyMaxSuccess (\_ -> 1000) do+    let check ::+          forall a b m.+          (GenIntegral a, IntegerConvert a b, IntegerNarrow b a) =>+          Monad m =>+          Hedgehog.PropertyT m ()+        check = do+          x :: a <- Hedgehog.forAll Gen.integral+          narrow (convert x :: b) === Just x -        let check :: forall a m. (GenIntegral a, BoundedBelow a) =>-                Exception.MonadCatch m => Hedgehog.PropertyT m ()-            check = do-                x :: Integer <- Hedgehog.forAll Gen.integral-                let y :: a = yolo x-                if x Ord.>= Num.toInteger (minBound @a)-                  then yolo y === x-                  else do-                      z <- Exception.try (pure $! y)-                      z === Either.Left Exception.Underflow+    it "A = Natural,  B = Integer" $ hedgehog $ check @Natural @Integer+    it "A = Natural,  B = Signed" $ hedgehog $ check @Natural @Signed+    it "A = Positive, B = Integer" $ hedgehog $ check @Positive @Integer+    it "A = Positive, B = Signed" $ hedgehog $ check @Positive @Signed+    it "A = Positive, B = Natural" $ hedgehog $ check @Positive @Natural -        it "A = Positive" $ hedgehog $ check @Positive-        it "A = Natural " $ hedgehog $ check @Natural+  describe+    "narrow x = (Just y | convert y = x) \+    \or Nothing"+    $ modifyMaxSuccess (\_ -> 1000) do+      let check ::+            forall a b m.+            (GenIntegral a, BoundedBelow b) =>+            (IntegerConvert b a, IntegerNarrow a b) =>+            (Show b, Eq b) =>+            Monad m =>+            Hedgehog.PropertyT m ()+          check = do+            x :: a <- Hedgehog.forAll Gen.integral+            let y :: Maybe b = narrow x+            if x Ord.>= convert (minBound @b)+              then do+                z <- evalMaybe y+                convert z === x+              else y === Nothing -    describe "toFinite x = (Just y | fromInteger y = x) \-             \or Nothing" $ modifyMaxSuccess (\_ -> 1000) do+      it "A = Integer, B = Natural" $ hedgehog $ check @Integer @Natural+      it "A = Signed,  B = Natural" $ hedgehog $ check @Signed @Natural+      it "A = Integer, B = Positive" $ hedgehog $ check @Integer @Positive+      it "A = Signed,  B = Positive" $ hedgehog $ check @Signed @Positive+      it "A = Natural, B = Positive" $ hedgehog $ check @Natural @Positive -        let check :: forall a b m. Monad m =>-                (ConvertWithFinite a, GenIntegral a, Show a) =>-                (Integer.Finite b, Eq b, Show b) =>-                Hedgehog.PropertyT m ()-            check = do-                x :: a <- Hedgehog.forAll Gen.integral-                let x' = Num.toInteger x-                let ok = x' Ord.>= Num.toInteger (Bounded.minBound :: b) Bool.&&-                        x' Ord.<= Num.toInteger (Bounded.maxBound :: b)-                (Integer.toFinite x :: Maybe b) ===-                    if ok then Just (Num.fromInteger x') else Nothing+  describe "yolo (yolo x) = x, if Integer x is in range of A" do+    let check ::+          forall a m.+          (GenIntegral a, BoundedBelow a) =>+          Exception.MonadCatch m =>+          Hedgehog.PropertyT m ()+        check = do+          x :: Integer <- Hedgehog.forAll Gen.integral+          let y :: a = yolo x+          if x Ord.>= Num.toInteger (minBound @a)+            then yolo y === x+            else do+              z <- Exception.try (pure $! y)+              z === Either.Left Exception.Underflow -        it "A = Integer,  B = Int " $ hedgehog $ check @Integer  @Int-        it "A = Integer,  B = Word" $ hedgehog $ check @Integer  @Word-        it "A = Natural,  B = Int " $ hedgehog $ check @Natural  @Int-        it "A = Natural,  B = Word" $ hedgehog $ check @Natural  @Word-        it "A = Positive, B = Int " $ hedgehog $ check @Positive @Int-        it "A = Positive, B = Word" $ hedgehog $ check @Positive @Word-        it "A = Signed,   B = Int " $ hedgehog $ check @Signed   @Int-        it "A = Signed,   B = Word" $ hedgehog $ check @Signed   @Word+    it "A = Positive" $ hedgehog $ check @Positive+    it "A = Natural " $ hedgehog $ check @Natural -    describe "fromFinite x = narrow (toInteger x)" do+  describe+    "toFinite x = (Just y | fromInteger y = x) \+    \or Nothing"+    $ modifyMaxSuccess (\_ -> 1000) do+      let check ::+            forall a b m.+            Monad m =>+            (ConvertWithFinite a, GenIntegral a, Show a) =>+            (Integer.Finite b, Eq b, Show b) =>+            Hedgehog.PropertyT m ()+          check = do+            x :: a <- Hedgehog.forAll Gen.integral+            let x' = Num.toInteger x+            let ok =+                  x' Ord.>= Num.toInteger (Bounded.minBound :: b)+                    Bool.&& x' Ord.<= Num.toInteger (Bounded.maxBound :: b)+            (Integer.toFinite x :: Maybe b)+              === if ok then Just (Num.fromInteger x') else Nothing -        let check :: forall a b m. Monad m =>-                (ConvertWithFinite a, IntegerNarrow Integer a, Eq a, Show a) =>-                (Finite b, GenFinite b, Show b) =>-                Hedgehog.PropertyT m ()-            check = do-                x :: b <- Hedgehog.forAll Gen.finite-                (Integer.fromFinite x :: Maybe a) === Integer.narrow (Num.toInteger x)+      it "A = Integer,  B = Int " $ hedgehog $ check @Integer @Int+      it "A = Integer,  B = Word" $ hedgehog $ check @Integer @Word+      it "A = Natural,  B = Int " $ hedgehog $ check @Natural @Int+      it "A = Natural,  B = Word" $ hedgehog $ check @Natural @Word+      it "A = Positive, B = Int " $ hedgehog $ check @Positive @Int+      it "A = Positive, B = Word" $ hedgehog $ check @Positive @Word+      it "A = Signed,   B = Int " $ hedgehog $ check @Signed @Int+      it "A = Signed,   B = Word" $ hedgehog $ check @Signed @Word -        it "A = Int,  B = Integer "  $ hedgehog $ check @Integer  @Int-        it "A = Word, B = Integer"   $ hedgehog $ check @Integer  @Word-        it "A = Int,  B = Natural "  $ hedgehog $ check @Natural  @Int-        it "A = Word, B = Natural"   $ hedgehog $ check @Natural  @Word-        it "A = Int,  B = Positive " $ hedgehog $ check @Positive @Int-        it "A = Word, B = Positive"  $ hedgehog $ check @Positive @Word-        it "A = Int,  B = Signed "   $ hedgehog $ check @Signed   @Int-        it "A = Word, B = Signed"    $ hedgehog $ check @Signed   @Word+  describe "fromFinite x = narrow (toInteger x)" do+    let check ::+          forall a b m.+          Monad m =>+          (ConvertWithFinite a, IntegerNarrow Integer a, Eq a, Show a) =>+          (Finite b, GenFinite b, Show b) =>+          Hedgehog.PropertyT m ()+        check = do+          x :: b <- Hedgehog.forAll Gen.finite+          (Integer.fromFinite x :: Maybe a) === Integer.narrow (Num.toInteger x) -    describe "Enum @Positive" $ do+    it "A = Int,  B = Integer " $ hedgehog $ check @Integer @Int+    it "A = Word, B = Integer" $ hedgehog $ check @Integer @Word+    it "A = Int,  B = Natural " $ hedgehog $ check @Natural @Int+    it "A = Word, B = Natural" $ hedgehog $ check @Natural @Word+    it "A = Int,  B = Positive " $ hedgehog $ check @Positive @Int+    it "A = Word, B = Positive" $ hedgehog $ check @Positive @Word+    it "A = Int,  B = Signed " $ hedgehog $ check @Signed @Int+    it "A = Word, B = Signed" $ hedgehog $ check @Signed @Word -        describe "[a ..]" $ do-            it "counts upward" $-                take 3 [5 :: Positive ..] `shouldBe` [5, 6, 7]-            it "can start with 1" $-                take 3 [1 :: Positive ..] `shouldBe` [1, 2, 3]+  describe "Enum @Positive" $ do+    describe "[a ..]" $ do+      it "counts upward" $+        take 3 [5 :: Positive ..] `shouldBe` [5, 6, 7]+      it "can start with 1" $+        take 3 [1 :: Positive ..] `shouldBe` [1, 2, 3] -        describe "[a .. b]" $ do-            it "counts upward" $-                [5 .. 8 :: Positive] `shouldBe` [5, 6, 7, 8]-            it "can start with 1" $-                [1 .. 5 :: Positive] `shouldBe` [1, 2, 3, 4, 5]-            it "does not count downward" $ do-                [8 .. 5 :: Positive] `shouldBe` []-                [8 .. 7 :: Positive] `shouldBe` []-            it "can return 1 item" $ do-                [3 .. 3 :: Positive] `shouldBe` [3]-                [1 .. 1 :: Positive] `shouldBe` [1]+    describe "[a .. b]" $ do+      it "counts upward" $+        [5 .. 8 :: Positive] `shouldBe` [5, 6, 7, 8]+      it "can start with 1" $+        [1 .. 5 :: Positive] `shouldBe` [1, 2, 3, 4, 5]+      it "does not count downward" $ do+        [8 .. 5 :: Positive] `shouldBe` []+        [8 .. 7 :: Positive] `shouldBe` []+      it "can return 1 item" $ do+        [3 .. 3 :: Positive] `shouldBe` [3]+        [1 .. 1 :: Positive] `shouldBe` [1] -        describe "[a, b ..]" $ do-            it "can count upward by 1" $ do-                take 5 [5, 6 :: Positive ..] `shouldBe` [5, 6, 7, 8, 9]-                take 5 [1, 2 :: Positive ..] `shouldBe` [1, 2, 3, 4, 5]-            it "can count downward by 1" $-                [5, 4 :: Positive ..] `shouldBe` [5, 4, 3, 2, 1]-            it "can count upward by 2" $ do-                take 5 [5, 7 :: Positive ..] `shouldBe` [5, 7, 9, 11, 13]-                take 5 [1, 3 :: Positive ..] `shouldBe` [1, 3, 5, 7, 9]-            it "can count downward by 2" $-                [9, 7 :: Positive ..] `shouldBe` [9, 7, 5, 3, 1]-            it "can count downward by 2 without exactly reaching its lower bound" $-                [8, 6 :: Positive ..] `shouldBe` [8, 6, 4, 2]-            it "can repeat 1 item indefinitely" $-                take 5 [4, 4 :: Positive ..] `shouldBe` [4, 4, 4, 4, 4]+    describe "[a, b ..]" $ do+      it "can count upward by 1" $ do+        take 5 [5, 6 :: Positive ..] `shouldBe` [5, 6, 7, 8, 9]+        take 5 [1, 2 :: Positive ..] `shouldBe` [1, 2, 3, 4, 5]+      it "can count downward by 1" $+        [5, 4 :: Positive ..] `shouldBe` [5, 4, 3, 2, 1]+      it "can count upward by 2" $ do+        take 5 [5, 7 :: Positive ..] `shouldBe` [5, 7, 9, 11, 13]+        take 5 [1, 3 :: Positive ..] `shouldBe` [1, 3, 5, 7, 9]+      it "can count downward by 2" $+        [9, 7 :: Positive ..] `shouldBe` [9, 7, 5, 3, 1]+      it "can count downward by 2 without exactly reaching its lower bound" $+        [8, 6 :: Positive ..] `shouldBe` [8, 6, 4, 2]+      it "can repeat 1 item indefinitely" $+        take 5 [4, 4 :: Positive ..] `shouldBe` [4, 4, 4, 4, 4] -        describe "[a, b .. c]" $ do-            it "can count upward by 1" $ do-                [5, 6 .. 9 :: Positive] `shouldBe` [5, 6, 7, 8, 9]-                [1, 2 .. 5 :: Positive] `shouldBe` [1, 2, 3, 4, 5]-            it "can count downward by 1" $-                [9, 8 .. 5 :: Positive] `shouldBe` [9, 8, 7, 6, 5]-            it "can count upward by 2" $ do-                [5, 7 .. 11 :: Positive] `shouldBe` [5, 7, 9, 11]-                [1, 3 .. 7 :: Positive] `shouldBe` [1, 3, 5, 7]-            it "can count upward without exactly reaching its upper bound" $-                [5, 7 .. 12 :: Positive] `shouldBe` [5, 7, 9, 11]-            it "can count downward by 2" $-                [11, 9 .. 5 :: Positive] `shouldBe` [11, 9, 7, 5]-            it "can count downward by 2 without exactly reaching its lower bound" $-                [11, 9 .. 4 :: Positive] `shouldBe` [11, 9, 7, 5]-            it "can count downward with a lower bound of 1" $ do-                [7, 5 .. 1 :: Positive] `shouldBe` [7, 5, 3, 1]-                [8, 6 .. 1 :: Positive] `shouldBe` [8, 6, 4, 2]-            it "can repeat 1 item indefinitely" $ do-                take 5 [4, 4 .. 9 :: Positive] `shouldBe` [4, 4, 4, 4, 4]-                take 5 [4, 4 .. 4 :: Positive] `shouldBe` [4, 4, 4, 4, 4]-            it "can return 1 item" $ do-                [4, 5 .. 4 :: Positive] `shouldBe` [4]-                [4, 3 .. 4 :: Positive] `shouldBe` [4]-            it "can return an empty list" $ do-                [4, 4 .. 3 :: Positive] `shouldBe` []-                [4, 5 .. 3 :: Positive] `shouldBe` []-                [5, 4 .. 6 :: Positive] `shouldBe` []+    describe "[a, b .. c]" $ do+      it "can count upward by 1" $ do+        [5, 6 .. 9 :: Positive] `shouldBe` [5, 6, 7, 8, 9]+        [1, 2 .. 5 :: Positive] `shouldBe` [1, 2, 3, 4, 5]+      it "can count downward by 1" $+        [9, 8 .. 5 :: Positive] `shouldBe` [9, 8, 7, 6, 5]+      it "can count upward by 2" $ do+        [5, 7 .. 11 :: Positive] `shouldBe` [5, 7, 9, 11]+        [1, 3 .. 7 :: Positive] `shouldBe` [1, 3, 5, 7]+      it "can count upward without exactly reaching its upper bound" $+        [5, 7 .. 12 :: Positive] `shouldBe` [5, 7, 9, 11]+      it "can count downward by 2" $+        [11, 9 .. 5 :: Positive] `shouldBe` [11, 9, 7, 5]+      it "can count downward by 2 without exactly reaching its lower bound" $+        [11, 9 .. 4 :: Positive] `shouldBe` [11, 9, 7, 5]+      it "can count downward with a lower bound of 1" $ do+        [7, 5 .. 1 :: Positive] `shouldBe` [7, 5, 3, 1]+        [8, 6 .. 1 :: Positive] `shouldBe` [8, 6, 4, 2]+      it "can repeat 1 item indefinitely" $ do+        take 5 [4, 4 .. 9 :: Positive] `shouldBe` [4, 4, 4, 4, 4]+        take 5 [4, 4 .. 4 :: Positive] `shouldBe` [4, 4, 4, 4, 4]+      it "can return 1 item" $ do+        [4, 5 .. 4 :: Positive] `shouldBe` [4]+        [4, 3 .. 4 :: Positive] `shouldBe` [4]+      it "can return an empty list" $ do+        [4, 4 .. 3 :: Positive] `shouldBe` []+        [4, 5 .. 3 :: Positive] `shouldBe` []+        [5, 4 .. 6 :: Positive] `shouldBe` [] -    describe "deepseq @Signed" $ do-        it "can succeed" $ do-            x <- force (NonZero MinusSign 5)-            x `shouldBe` Right (-5)-        it "can force an error" $ do-            x <- force (throw X :: Signed)-            x `shouldBe` Left X-        it "can force an error in sign" $ do-            x <- force (NonZero (throw X) 5)-            x `shouldBe` Left X-        it "can force an error in magnitude" $ do-            x <- force (NonZero MinusSign (throw X))-            x `shouldBe` Left X+  describe "deepseq @Signed" $ do+    it "can succeed" $ do+      x <- force (NonZero MinusSign 5)+      x `shouldBe` Right (-5)+    it "can force an error" $ do+      x <- force (throw X :: Signed)+      x `shouldBe` Left X+    it "can force an error in sign" $ do+      x <- force (NonZero (throw X) 5)+      x `shouldBe` Left X+    it "can force an error in magnitude" $ do+      x <- force (NonZero MinusSign (throw X))+      x `shouldBe` Left X -    describe "length" $ do-        it "Natural" $ Natural.length "abc" `shouldBe` 3-        it "Positive" $ Positive.length ('a' :| "bc") `shouldBe` 3+  describe "length" $ do+    it "Natural" $ Natural.length "abc" `shouldBe` 3+    it "Positive" $ Positive.length ('a' :| "bc") `shouldBe` 3  data X = X-    deriving stock (Eq, Show)+  deriving stock (Eq, Show)  instance Exception X