packages feed

nat-optics 1.0.0.2 → 1.0.0.3

raw patch · 14 files changed

+196/−149 lines, 14 filesdep +hspecdep ~textPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: hspec

Dependency ranges changed: text

API changes (from Hackage documentation)

- NatOptics.NonNegative: instance GHC.Classes.Eq number => GHC.Classes.Eq (NatOptics.NonNegative.NonNegative number)
- NatOptics.NonNegative: instance GHC.Classes.Ord number => GHC.Classes.Ord (NatOptics.NonNegative.NonNegative number)
- NatOptics.NonNegative: instance GHC.Show.Show number => GHC.Show.Show (NatOptics.NonNegative.NonNegative number)
- NatOptics.Positive: instance GHC.Classes.Eq number => GHC.Classes.Eq (NatOptics.Positive.Positive number)
- NatOptics.Positive: instance GHC.Classes.Ord number => GHC.Classes.Ord (NatOptics.Positive.Positive number)
- NatOptics.Positive: instance GHC.Show.Show number => GHC.Show.Show (NatOptics.Positive.Positive number)
+ NatOptics.NonNegative.Unsafe: NonNegativeUnsafe :: number -> NonNegative number
+ NatOptics.NonNegative.Unsafe: [number] :: NonNegative number -> number
+ NatOptics.NonNegative.Unsafe: instance GHC.Classes.Eq number => GHC.Classes.Eq (NatOptics.NonNegative.Unsafe.NonNegative number)
+ NatOptics.NonNegative.Unsafe: instance GHC.Classes.Ord number => GHC.Classes.Ord (NatOptics.NonNegative.Unsafe.NonNegative number)
+ NatOptics.NonNegative.Unsafe: instance GHC.Show.Show number => GHC.Show.Show (NatOptics.NonNegative.Unsafe.NonNegative number)
+ NatOptics.NonNegative.Unsafe: newtype NonNegative number
+ NatOptics.Positive.Math: minus :: (Num n, Ord n) => Positive n -> Positive n -> Signed n
+ NatOptics.Positive.Math: plus :: Num n => Positive n -> Positive n -> Positive n
+ NatOptics.Positive.Unsafe: PositiveUnsafe :: number -> Positive number
+ NatOptics.Positive.Unsafe: [number] :: Positive number -> number
+ NatOptics.Positive.Unsafe: instance GHC.Classes.Eq number => GHC.Classes.Eq (NatOptics.Positive.Unsafe.Positive number)
+ NatOptics.Positive.Unsafe: instance GHC.Classes.Ord number => GHC.Classes.Ord (NatOptics.Positive.Unsafe.Positive number)
+ NatOptics.Positive.Unsafe: instance GHC.Show.Show number => GHC.Show.Show (NatOptics.Positive.Unsafe.Positive number)
+ NatOptics.Positive.Unsafe: newtype Positive number
+ NatOptics.Signed: Minus :: Positive n -> Signed n
+ NatOptics.Signed: Plus :: Positive n -> Signed n
+ NatOptics.Signed: Zero :: Signed n
+ NatOptics.Signed: data Signed n
+ NatOptics.Signed: instance GHC.Classes.Eq n => GHC.Classes.Eq (NatOptics.Signed.Signed n)
+ NatOptics.Signed: instance GHC.Classes.Ord n => GHC.Classes.Ord (NatOptics.Signed.Signed n)
+ NatOptics.Signed: instance GHC.Show.Show n => GHC.Show.Show (NatOptics.Signed.Signed n)
+ NatOptics.Signed: intIso :: Iso' Integer (Signed Integer)

Files

− changelog.txt
@@ -1,3 +0,0 @@-v1 - Initial release-v1.0.0.1 - Added tests, added a few examples to the docs-v1.0.0.2 - Support GHC 9.2 and text-2.0, drop hedgehog dependency
license.txt view
@@ -1,4 +1,4 @@-Copyright 2021 Mission Valley Software LLC+Copyright 2021-2022 Mission Valley Software LLC  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in
nat-optics.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: nat-optics-version: 1.0.0.2+version: 1.0.0.3 category: Numeric, Optics  synopsis:@@ -17,7 +17,7 @@     to cover basic usage, but you probably also want to import     the "Optics" module from the `optics` package. -copyright: 2021 Mission Valley Software LLC+copyright: 2021-2022 Mission Valley Software LLC license: MIT license-file: license.txt @@ -29,8 +29,6 @@  build-type: Simple -extra-source-files: changelog.txt- source-repository head   type: git   location: https://github.com/typeclasses/nat-optics@@ -39,37 +37,33 @@     default-language:   Haskell2010     ghc-options:        -Wall     default-extensions: DerivingStrategies+                      , FlexibleContexts                       , GeneralizedNewtypeDeriving                       , NoImplicitPrelude                       , TypeApplications  common dependencies-    build-depends:      base        ^>= 4.14  || ^>= 4.15 || ^>= 4.16-                      , text        ^>= 1.2.3 || ^>= 2.0+    build-depends:      base ^>= 4.14 || ^>= 4.15 || ^>= 4.16+                      , text ^>= 1.2.3.2 || ^>= 2.0                       , optics-core ^>= 0.4 -common test-    import:             language-                      , dependencies-    build-depends:      nat-optics-    other-modules:      TestPrelude- library     import:             language                       , dependencies     hs-source-dirs:     src     exposed-modules:    NatOptics.NonNegative+                      , NatOptics.NonNegative.Unsafe                       , NatOptics.Positive+                      , NatOptics.Positive.Math+                      , NatOptics.Positive.Unsafe+                      , NatOptics.Signed     other-modules:      NatOptics.Internal -test-suite NonNegative-    import:             test-    type:               exitcode-stdio-1.0-    hs-source-dirs:     test-    main-is:            NonNegative.hs--test-suite Positive-    import:             test+test-suite nat-optics-test+    import:             language+                      , dependencies     type:               exitcode-stdio-1.0     hs-source-dirs:     test-    main-is:            Positive.hs+    main-is:            Main.hs+    build-depends:      nat-optics+                      , hspec ^>= 2.8 || ^>= 2.9 || ^>= 2.10
src/NatOptics/Internal.hs view
@@ -1,4 +1,10 @@-module NatOptics.Internal ( strNat, textStr ) where+{-# language Trustworthy #-}++module NatOptics.Internal+  (+    strNat, textStr,+  )+  where  import Control.Monad   ( mfilter ) import Data.Eq         ( (==) )
src/NatOptics/NonNegative.hs view
@@ -1,3 +1,5 @@+{-# language Trustworthy #-}+ module NatOptics.NonNegative   (     {- * Type constructor -} NonNegative,@@ -6,13 +8,12 @@                              natIso, textPrism, stringPrism,      {- * Re-exports -}       Natural, Integer, Prism', Iso',-                             view, review, preview+                             view, review, preview,   ) where  import Control.Applicative ( (*>) ) import Control.Monad       ( guard ) import Data.Bits           ( Bits, toIntegralSized )-import Data.Eq             ( Eq ) import Data.Function       ( (.) ) import Data.Functor        ( fmap, ($>), (<$>) ) import Data.Maybe          ( Maybe )@@ -29,10 +30,8 @@ import Optics.Review       ( review ) import Prelude             ( Integer, Integral, Num,                              fromIntegral, toInteger )-import Text.Show           ( Show ) -newtype NonNegative number = NonNegative{ number :: number }-    deriving newtype (Eq, Ord, Show)+import NatOptics.NonNegative.Unsafe (NonNegative (..))  {- | For any numeric type @n@,      @'NonNegative' n@ is a subset of @n@.@@ -53,7 +52,7 @@ natPrism =     prism'         (fromIntegral . number)-        (fmap NonNegative . toIntegralSized) {- No need to verify+        (fmap NonNegativeUnsafe . toIntegralSized) {- No need to verify             here, because Natural is always non-negative. The only             check here is when converting from 'Natural' to ensure             that it does not overflow the max bound of 'n'. -}@@ -65,7 +64,7 @@  {- | 'Natural' and @'NonNegative' 'Natural'@ are the same thing. -} natIso :: Iso' Natural (NonNegative Natural)-natIso = iso NonNegative number+natIso = iso NonNegativeUnsafe number  stringPrism :: (Integral n, Bits n) => Prism' String (NonNegative n) stringPrism = strNat % natPrism@@ -74,8 +73,8 @@ textPrism = textStr % stringPrism  verify :: (Ord n, Num n) => n -> Maybe (NonNegative n)-verify n = guard (n >= 0) $> NonNegative n+verify n = guard (n >= 0) $> NonNegativeUnsafe n  verifyAndResize :: (Integral a, Integral b, Bits a, Bits b)                 => a -> Maybe (NonNegative b)-verifyAndResize x = verify x *> (NonNegative <$> toIntegralSized x)+verifyAndResize x = verify x *> (NonNegativeUnsafe <$> toIntegralSized x)
+ src/NatOptics/NonNegative/Unsafe.hs view
@@ -0,0 +1,14 @@+{-# language Unsafe #-}++module NatOptics.NonNegative.Unsafe+  (+    NonNegative (..),+  )+  where++import Data.Eq   ( Eq )+import Data.Ord  ( Ord )+import Text.Show ( Show )++newtype NonNegative number = NonNegativeUnsafe{ number :: number }+    deriving newtype (Eq, Ord, Show)
src/NatOptics/Positive.hs view
@@ -1,3 +1,5 @@+{-# language Trustworthy #-}+ module NatOptics.Positive   (     {- * Type constructor -} Positive,@@ -6,13 +8,12 @@                              textPrism, stringPrism,      {- * Re-exports -}       Natural, Integer, Prism',-                             view, review, preview+                             view, review, preview,   ) where  import Control.Applicative ( (*>) ) import Control.Monad       ( guard ) import Data.Bits           ( Bits, toIntegralSized )-import Data.Eq             ( Eq ) import Data.Function       ( (.) ) import Data.Functor        ( ($>), (<$>) ) import Data.Maybe          ( Maybe )@@ -28,10 +29,8 @@ import Optics.Review       ( review ) import Prelude             ( Integer, Integral, Num,                              fromIntegral, toInteger )-import Text.Show           ( Show ) -newtype Positive number = Positive{ number :: number }-    deriving newtype (Eq, Ord, Show)+import NatOptics.Positive.Unsafe (Positive (..))  {- | For any numeric type @n@,      @'Positive' n@ is a subset of @n@.@@ -63,7 +62,7 @@ textPrism = textStr % stringPrism  verify :: (Num n, Ord n) => n -> Maybe (Positive n)-verify n = guard (n > 0) $> Positive n+verify n = guard (n > 0) $> PositiveUnsafe n  verifyAndResize :: (Integral a, Integral b, Bits a, Bits b) => a -> Maybe (Positive b)-verifyAndResize x = verify x *> (Positive <$> toIntegralSized x)+verifyAndResize x = verify x *> (PositiveUnsafe <$> toIntegralSized x)
+ src/NatOptics/Positive/Math.hs view
@@ -0,0 +1,33 @@+{-# language Trustworthy #-}++module NatOptics.Positive.Math+  (+    minus,+    plus,+  )+  where++import Data.Maybe          ( Maybe (..) )+import Data.Ord            ( Ord, (<) )+import Optics.Core         ( preview, review )+import Prelude             ( Num, abs, (+), (-) )++import NatOptics.Positive.Unsafe ( Positive (..) )+import qualified NatOptics.Positive as Positive++import NatOptics.Signed ( Signed )+import qualified NatOptics.Signed as Signed++plus :: Num n => Positive n -> Positive n -> Positive n+plus (PositiveUnsafe a) (PositiveUnsafe b) = PositiveUnsafe (a + b)++minus :: (Num n, Ord n) => Positive n -> Positive n -> Signed n+minus a b =+    let+        a' = review Positive.refine a+        b' = review Positive.refine b+        diff = a' - b'+    in+        case preview Positive.refine (abs diff) of+            Nothing -> Signed.Zero+            Just diff' -> if diff < 0 then Signed.Minus diff' else Signed.Plus diff'
+ src/NatOptics/Positive/Unsafe.hs view
@@ -0,0 +1,10 @@+{-# language Unsafe #-}++module NatOptics.Positive.Unsafe where++import Data.Eq   ( Eq )+import Data.Ord  ( Ord )+import Text.Show ( Show )++newtype Positive number = PositiveUnsafe{ number :: number }+    deriving newtype (Eq, Ord, Show)
+ src/NatOptics/Signed.hs view
@@ -0,0 +1,31 @@+{-# language Trustworthy #-}++module NatOptics.Signed+  (+    Signed (..),+    intIso,+  )+  where++import Data.Eq            ( Eq )+import Data.Ord           ( Ord, compare, Ordering (..) )+import Text.Show          ( Show )+import Optics.Core        ( Iso', iso )+import Prelude            ( Integer, abs, negate )++import NatOptics.Positive.Unsafe ( Positive (..) )++data Signed n = Zero | Minus (Positive n) | Plus (Positive n)+    deriving stock (Eq, Ord, Show)++intIso :: Iso' Integer (Signed Integer)+intIso = iso f g+  where+    f x = case compare x 0 of+        EQ -> Zero+        LT -> Minus (PositiveUnsafe (abs x))+        GT -> Plus (PositiveUnsafe x)+    g y = case y of+        Zero -> 0+        Plus (PositiveUnsafe x) -> x+        Minus (PositiveUnsafe x) -> negate x
+ test/Main.hs view
@@ -0,0 +1,71 @@+module Main (main) where++import Test.Hspec+import Prelude++import Data.Int (Int16, Int32)+import Data.Maybe (isNothing)+import Optics.Core (preview, review, view)++import qualified NatOptics.Positive as Pos+import qualified NatOptics.Positive.Unsafe as Pos+import qualified NatOptics.Positive.Math as Pos.Math+import qualified NatOptics.NonNegative as NN+import qualified NatOptics.NonNegative.Unsafe as NN+import qualified NatOptics.Signed as S++main :: IO ()+main = hspec $ do+    nonNegativeSpec+    positiveSpec+    signedSpec+    mathSpec++nonNegativeSpec :: SpecWith ()+nonNegativeSpec = describe "NonNegative" $ do+    describe "0" $ do+        specify "preview stringPrism" $ preview (NN.stringPrism @Int32) "0" `shouldBe` Just (NN.NonNegativeUnsafe 0)+        specify "review refine" $ review NN.refine (NN.NonNegativeUnsafe @Int32 0) `shouldBe` 0+        specify "review stringPrism" $ review NN.stringPrism (NN.NonNegativeUnsafe @Int32 0) `shouldBe` "0"+    describe "57" $ do+        specify "preview stringPrism" $ preview (NN.stringPrism @Int32) "57" `shouldBe` Just (NN.NonNegativeUnsafe 57)+        specify "refine" $ review NN.refine (NN.NonNegativeUnsafe @Int32 57) `shouldBe` 57+        specify "stringPrism" $ review NN.stringPrism (NN.NonNegativeUnsafe @Int32 57) `shouldBe` "57"+    describe "preview stringPrism" $ do+        let examples = [ "-0", "-1", "00", "𝟝𝟟", "57 ", "057", "9999999999999999999999999999" ]+        specify "failures" $ all (isNothing . preview (NN.stringPrism @Int32)) examples++positiveSpec :: SpecWith ()+positiveSpec = describe "Positive" $ do+    describe "1" $ do+        specify "preview stringPrism" $ preview (Pos.stringPrism @Int16) "1" `shouldBe` Just (Pos.PositiveUnsafe 1)+        specify "refine" $ review Pos.refine (Pos.PositiveUnsafe @Int16 1) `shouldBe` 1+        specify "stringPrism" $ review Pos.stringPrism (Pos.PositiveUnsafe @Int16 1) `shouldBe` "1"+    describe "57" $ do+        specify "preview stringPrism" $ preview (Pos.stringPrism @Int16) "57" `shouldBe` Just (Pos.PositiveUnsafe 57)+        specify "refine" $ review Pos.refine (Pos.PositiveUnsafe @Int16 57) `shouldBe` 57+        specify "stringPrism" $ review Pos.stringPrism (Pos.PositiveUnsafe @Int16 57) `shouldBe` "57"+    describe "stringPrism" $ do+        let examples = [ "0", "-0", "-1", "00", "𝟝𝟟", "57 ", "057", "99999999999999999999999" ]+        specify "failures" $ all (isNothing . preview (Pos.stringPrism @Int16)) examples++signedSpec :: SpecWith ()+signedSpec = describe "Signed" $ do+    describe "intIso" $ do+        describe "view" $ do+            specify "0" $ view S.intIso 0 `shouldBe` S.Zero+            specify "3" $ view S.intIso 3 `shouldBe` S.Plus (Pos.PositiveUnsafe 3)+            specify "-5" $ view S.intIso (-5) `shouldBe` S.Minus (Pos.PositiveUnsafe 5)+        describe "review" $ do+            specify "0" $ review S.intIso S.Zero `shouldBe` 0+            specify "3" $ review S.intIso (S.Plus (Pos.PositiveUnsafe 3)) `shouldBe` 3+            specify "-5" $ review S.intIso (S.Minus (Pos.PositiveUnsafe 5)) `shouldBe` (-5)++mathSpec :: SpecWith ()+mathSpec = describe "Positive math" $ do+    describe "plus" $ do+        specify "10 + 5" $ Pos.Math.plus (Pos.PositiveUnsafe 10) (Pos.PositiveUnsafe 5) `shouldBe` Pos.PositiveUnsafe @Int32 15+    describe "minus" $ do+        specify "3 - 3" $ Pos.Math.minus (Pos.PositiveUnsafe 3) (Pos.PositiveUnsafe 3) `shouldBe` S.Zero @Int32+        specify "3 - 5" $ Pos.Math.minus (Pos.PositiveUnsafe 3) (Pos.PositiveUnsafe 5) `shouldBe` S.Minus @Int32 (Pos.PositiveUnsafe 2)+        specify "9 - 5" $ Pos.Math.minus (Pos.PositiveUnsafe 9) (Pos.PositiveUnsafe 5) `shouldBe` S.Plus @Int32 (Pos.PositiveUnsafe 4)
− test/NonNegative.hs
@@ -1,39 +0,0 @@-module Main (main) where--import NatOptics.NonNegative-import TestPrelude--main :: IO ()-main = main' failures--failures :: [Failure]-failures =-    case preview (stringPrism @Int32) "0" of-        Nothing -> fail' "preview (stringPrism @Int32) \"0\" = Nothing"-        Just n ->-            case review refine n of-                0 -> okay-                result -> fail' $ "review refine" ! show' n ! "=" ! show result-            <>-            case review stringPrism n of-                "0" -> okay-                result -> fail' $ "review stringPrism" ! show' n ! "=" ! show result-    <>-    case preview (stringPrism @Int32) "57" of-        Nothing -> fail' "preview (stringPrism @Int32) \"57\" = Nothing"-        Just n ->-            case review refine n of-                57 -> okay-                result -> fail' $ "review refine" ! show' n ! "=" ! show result-            <>-            case review stringPrism n of-                "57" -> okay-                result -> fail' $ "review stringPrism" ! show' n ! "=" ! show result-    <>-    foldMap-        (\x -> case preview (stringPrism @Int32) x of-            Nothing -> okay-            result -> fail' $ "preview (stringPrism @Int32)" ! show' x ! "=" ! show result-        )-        [ "-0", "-1", "00", "𝟝𝟟", "57 ", "057"-        , "9999999999999999999999999999" ]
− test/Positive.hs
@@ -1,39 +0,0 @@-module Main (main) where--import NatOptics.Positive-import TestPrelude--main :: IO ()-main = main' failures--failures :: [Failure]-failures =-    case preview (stringPrism @Int16) "1" of-        Nothing -> fail' "preview (stringPrism @Int16) \"1\" = Nothing"-        Just n ->-            case review refine n of-                1 -> okay-                result -> fail' $ "review refine" ! show' n ! "=" ! show result-            <>-            case review stringPrism n of-                "1" -> okay-                result -> fail' $ "review stringPrism" ! show' n ! "=" ! show result-    <>-    case preview (stringPrism @Int16) "57" of-        Nothing -> fail' "preview (stringPrism @Int16) \"57\" = Nothing"-        Just n ->-            case review refine n of-                57 -> okay-                result -> fail' $ "review refine" ! show' n ! "=" ! show result-            <>-            case review stringPrism n of-                "57" -> okay-                result -> fail' $ "review stringPrism" ! show' n ! "=" ! show result-    <>-    foldMap-        (\x -> case preview (stringPrism @Int16) x of-            Nothing -> okay-            result -> fail' $ "preview (stringPrism @Int16)" ! show' x ! "=" ! show result-        )-        [ "0", "-0", "-1", "00", "𝟝𝟟", "57 ", "057"-        , "99999999999999999999999" ]
− test/TestPrelude.hs
@@ -1,29 +0,0 @@-module TestPrelude (module X, Failure (..), main', show', okay, fail', (!)) where--import Control.Monad as X-import Data.Foldable as X-import Data.Int as X-import Optics.Optic as X-import Optics.Re as X-import Prelude as X-import System.Exit as X--data Failure = Failure String--main' :: [Failure] -> IO ()-main' failures =-    unless (null failures) $ do-        for_ failures $ \(Failure x) -> putStrLn ("🔥 " ++ x)-        exitFailure--show' :: Show a => a -> String-show' x = showsPrec 11 x ""--okay :: [Failure]-okay = []--fail' :: String -> [Failure]-fail' x = [Failure x]--(!) :: String -> String -> String-x ! y = x <> " " <> y