packages feed

d10 0.2.1.6 → 0.3

raw patch · 13 files changed

+1062/−236 lines, 13 filesdep +d10dep +hedgehogdep −doctestdep ~basedep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependencies added: d10, hedgehog

Dependencies removed: doctest

Dependency ranges changed: base, template-haskell

API changes (from Hackage documentation)

- Data.D10.Char: isD10Str :: String -> Bool
- Data.D10.Num: isD10Str :: String -> Bool
- Data.D10.Safe: d10 :: QuasiQuoter
- Data.D10.Safe: d10Exp :: Integral a => a -> Q Exp
- Data.D10.Safe: d10Pat :: D10 -> Q Pat
+ Data.D10.Safe: instance Data.Data.Data Data.D10.Safe.D10
+ Data.D10.Safe: instance GHC.Generics.Generic Data.D10.Safe.D10
- Data.D10.Char: d10Exp :: Integral a => a -> Q Exp
+ Data.D10.Char: d10Exp :: Integer -> Q Exp
- Data.D10.Char: d10ListPat :: [D10] -> Q Pat
+ Data.D10.Char: d10ListPat :: String -> Q Pat
- Data.D10.Char: d10Pat :: D10 -> Q Pat
+ Data.D10.Char: d10Pat :: Integer -> Q Pat
- Data.D10.Num: d10 :: forall a. (Lift a, Integral a) => QuasiQuoter
+ Data.D10.Num: d10 :: QuasiQuoter
- Data.D10.Num: d10Exp :: forall a b. (Integral b, Lift a, Num a) => b -> Q Exp
+ Data.D10.Num: d10Exp :: Integer -> Q Exp
- Data.D10.Num: d10ListExp :: forall a. (Lift a, Num a) => String -> Q Exp
+ Data.D10.Num: d10ListExp :: String -> Q Exp
- Data.D10.Num: d10ListPat :: Integral a => [D10 a] -> Q Pat
+ Data.D10.Num: d10ListPat :: String -> Q Pat
- Data.D10.Num: d10Pat :: Integral a => D10 a -> Q Pat
+ Data.D10.Num: d10Pat :: Integer -> Q Pat
- Data.D10.Num: d10list :: forall a. (Lift a, Integral a) => QuasiQuoter
+ Data.D10.Num: d10list :: QuasiQuoter
- Data.D10.Safe: d10ListPat :: [D10] -> Q Pat
+ Data.D10.Safe: d10ListPat :: String -> Q Pat

Files

CHANGELOG.md view
@@ -40,3 +40,56 @@ **v0.2.1.6**    * Support `doctest-0.17`++**v0.3**++In module `Data.D10.Char`:++  * Removed `isD10Str` (see `Data.D10.Predicate`)+  * Type of `d10Exp` changed+    from `Integral a => a -> Q Exp`+    to `Integer -> Q Exp`+  * Type of `d10Pat` changed+    from `D10 -> Q Pat`+    to `Integer -> Q Pat`+  * Type of `d10ListPat` changed+    from `[D10] -> Q Pat`+    to `String -> Q Pat`++In module `Data.D10.Num`:++  * Removed `isD10Str` (see `Data.D10.Predicate`)+  * Type of `d10Exp` changed+    from `(Integral b, Lift a, Num a) => b -> Q Exp`+    to `Integer -> Q Exp`+  * Type of `d10ListExp` changed+    from `(Lift a, Num a) => String -> Q Exp`+    to `String -> Q Exp`+  * Type of `d10Pat` changed+    from `Integral a => D10 a -> Q Pat`+    to `Integer -> Q Pat`+  * Type of `d10ListPat` changed+    from `Integral a => [D10 a] -> Q Pat`+    to `String -> Q Pat`+  * Type of `d10` changed+    from `(Lift a, Integral a) => QuasiQuoter`+    to `QuasiQuoter`+  * Type of `d10list` changed+    from `(Lift a, Integral a) => QuasiQuoter`+    to `QuasiQuoter`+  * Although type variables no longer appear in the+    various Template Haskell functions, the expressions+    and patterns they generate are polymorphic.++In module `Data.D10.Safe`:++  * The `D10` type now has instances of the `Data` and `Generic`.+  * Type of `d10ListPat` changed+    from `[D10] -> Q Pat`+    to `String -> Q Pat`+  * Removed `d10Exp`, `d10Pat`, and `d10`++Other changes:++  * `doctest` test dependency has been removed, and+    `hedgehog` dependency has been added instead
d10.cabal view
@@ -1,5 +1,7 @@+cabal-version: 2.2+ name: d10-version: 0.2.1.6+version: 0.3 category: Data synopsis: Digits 0-9 @@ -48,12 +50,11 @@ author:     Chris Martin maintainer: Chris Martin, Julie Moronuki -copyright: 2018 Typeclass Consulting, LLC+copyright: 2018-2021 Mission Valley Software LLC license: MIT license-file: license.txt  build-type: Simple-cabal-version: >= 1.10  tested-with:     GHC == 8.2.2@@ -72,11 +73,15 @@  library   default-language: Haskell2010+  ghc-options: -Wall   hs-source-dirs: src    build-depends:-      base             >= 4.10 && < 4.15-    , template-haskell >= 2.12 && < 2.17+      base ^>= 4.10 || ^>= 4.11 || ^>= 4.12+        || ^>= 4.13 || ^>= 4.14+    , template-haskell+           ^>= 2.12 || ^>= 2.13 || ^>= 2.14+        || ^>= 2.15 || ^>= 2.16    exposed-modules:       Data.D10.Char@@ -84,13 +89,110 @@     , Data.D10.Predicate     , Data.D10.Safe -test-suite doctest+  default-extensions:+      DeriveDataTypeable+      DeriveGeneric+      DeriveLift+      DerivingStrategies+      GeneralizedNewtypeDeriving+      InstanceSigs+      QuasiQuotes+      ScopedTypeVariables+      TemplateHaskell+      TypeApplications++test-suite char   default-language: Haskell2010+  ghc-options: -Wall   hs-source-dirs: test   type: exitcode-stdio-1.0-  main-is: doctest.hs-  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  main-is: char.hs +  other-modules:+      AssertQFails+      Fallible+   build-depends:-      base             >= 4.10 && < 4.15-    , doctest          >= 0.13 && < 0.18+      d10+    , base ^>= 4.10 || ^>= 4.11 || ^>= 4.12+        || ^>= 4.13 || ^>= 4.14+    , hedgehog ^>= 1.0+    , template-haskell+           ^>= 2.12 || ^>= 2.13 || ^>= 2.14+        || ^>= 2.15 || ^>= 2.16++  default-extensions:+      DeriveDataTypeable+      DeriveGeneric+      DeriveLift+      DerivingStrategies+      GeneralizedNewtypeDeriving+      InstanceSigs+      QuasiQuotes+      ScopedTypeVariables+      TemplateHaskell+      TypeApplications++test-suite num+  default-language: Haskell2010+  ghc-options: -Wall+  hs-source-dirs: test+  type: exitcode-stdio-1.0+  main-is: num.hs++  other-modules:+      AssertQFails+      Fallible++  build-depends:+      d10+    , base ^>= 4.10 || ^>= 4.11 || ^>= 4.12+        || ^>= 4.13 || ^>= 4.14+    , hedgehog ^>= 1.0+    , template-haskell+           ^>= 2.12 || ^>= 2.13 || ^>= 2.14+        || ^>= 2.15 || ^>= 2.16++  default-extensions:+      DeriveDataTypeable+      DeriveGeneric+      DeriveLift+      DerivingStrategies+      GeneralizedNewtypeDeriving+      InstanceSigs+      QuasiQuotes+      ScopedTypeVariables+      TemplateHaskell+      TypeApplications++test-suite safe+  default-language: Haskell2010+  ghc-options: -Wall+  hs-source-dirs: test+  type: exitcode-stdio-1.0+  main-is: safe.hs++  other-modules:+      AssertQFails+      Fallible++  build-depends:+      d10+    , base ^>= 4.10 || ^>= 4.11 || ^>= 4.12+        || ^>= 4.13 || ^>= 4.14+    , hedgehog ^>= 1.0+    , template-haskell+           ^>= 2.12 || ^>= 2.13 || ^>= 2.14+        || ^>= 2.15 || ^>= 2.16++  default-extensions:+      DeriveDataTypeable+      DeriveGeneric+      DeriveLift+      DerivingStrategies+      GeneralizedNewtypeDeriving+      InstanceSigs+      QuasiQuotes+      ScopedTypeVariables+      TemplateHaskell+      TypeApplications
license.txt view
@@ -1,4 +1,4 @@-Copyright 2018 Typeclass Consulting, LLC+Copyright 2018-2021 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 the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 
src/Data/D10/Char.hs view
@@ -1,8 +1,3 @@-{-# LANGUAGE DeriveLift       #-}-{-# LANGUAGE InstanceSigs     #-}-{-# LANGUAGE TemplateHaskell  #-}-{-# LANGUAGE TypeApplications #-}- -- | Defines a 'D10' type as a newtype for 'Char', where the -- values are restricted to characters between @'0'@ and @'9'@. --@@ -42,7 +37,6 @@     , strD10Maybe     , strD10Either     , strD10Fail-    , isD10Str      -- * Converting between [D10] and String     , strD10ListMaybe@@ -89,20 +83,15 @@ import Control.Monad.Fail (MonadFail (fail)) import Data.Char          (chr, ord) import Data.Monoid        (Endo (..))-import GHC.Generics       (Generic) import Numeric.Natural    (Natural) import Prelude            hiding (fail, (+), (-), (*))  import qualified Prelude as P  -- template-haskell+import Language.Haskell.TH.Lib    (litP, charL) import Language.Haskell.TH.Quote  (QuasiQuoter (..))-import Language.Haskell.TH.Syntax (Exp (..), Lift (lift), Lit (..), Pat (..), Q)---- $setup--- >>> :set -XQuasiQuotes--- >>> :set -XTemplateHaskell--- >>> :set -fno-warn-overlapping-patterns+import Language.Haskell.TH.Syntax (Exp (..), Lift, Pat (..), Q)  --------------------------------------------------- @@ -356,7 +345,7 @@ -- in the string are within the range @'0'@ to @'9'@, or produce -- 'Nothing' otherwise. ----- @'Data.D10.Predicate.isD10Str' x = 'Data.Maybe.isJust' ('strD10ListMaybe' x)@+-- @'Data.D10.Predicate.isD10ListStr' x = 'Data.Maybe.isJust' ('strD10ListMaybe' x)@ -- -- 'strD10ListFail' is a more general version of this function. --@@ -728,9 +717,12 @@ -- You may also be interested in 'd10', a quasi-quoter which -- does something similar. -d10Exp :: Integral a => a -> Q Exp-d10Exp = integralD10Fail >=> (lift :: D10 -> Q Exp)+d10Exp :: Integer -> Q Exp+d10Exp = integerD10Fail >=> d10Exp' +d10Exp' :: D10 -> Q Exp+d10Exp' x = [| x |]+ -- | Produces an expression of type @['D10']@ that can be used -- in a Template Haskell splice. --@@ -752,8 +744,11 @@ -- does something similar.  d10ListExp :: String -> Q Exp-d10ListExp = strD10ListFail >=> (lift :: [D10] -> Q Exp)+d10ListExp = strD10ListFail >=> d10ListExp' +d10ListExp' :: [D10] -> Q Exp+d10ListExp' xs = [| xs |]+ ---------------------------------------------------  -- | Produces a pattern that can be used in a splice@@ -761,36 +756,35 @@ -- -- >>> :{ --       case (charD10Maybe '5') of---         Just $(d10Pat [d10|4|]) -> "A"---         Just $(d10Pat [d10|5|]) -> "B"---         _                       -> "C"+--         Just $(d10Pat 4) -> "A"+--         Just $(d10Pat 5) -> "B"+--         _                -> "C" -- >>> :} -- "B" -- -- You may wish to use the 'd10' quasi-quoter instead. -d10Pat :: D10 -> Q Pat-d10Pat x =-    return (ConP 'D10_Unsafe [LitP (CharL (d10Char x))])+d10Pat :: Integer -> Q Pat+d10Pat = integerD10Fail >=> d10Pat' +d10Pat' :: D10 -> Q Pat+d10Pat' (D10_Unsafe x) = [p| D10_Unsafe $(litP $ charL x) |]+ -- | Produces a pattern that can be used in a splice -- to match a particular list of 'D10' values. -- -- >>> :{ --       case (strD10ListMaybe "56") of---         Just $(d10ListPat [d10list|42|]) -> "A"---         Just $(d10ListPat [d10list|56|]) -> "B"---         _                                -> "C"+--         Just $(d10ListPat "42") -> "A"+--         Just $(d10ListPat "56") -> "B"+--         _                       -> "C" -- >>> :} -- "B" -- -- You may wish to use the 'd10list' quasi-quoter instead. -d10ListPat :: [D10] -> Q Pat-d10ListPat xs =-  do-    pats <- traverse d10Pat xs-    return (ListP pats)+d10ListPat :: String -> Q Pat+d10ListPat = strD10ListFail >=> foldr (\x p -> [p| $(d10Pat' x) : $(p) |]) [p| [] |]  -------------------------------------------------- @@ -834,8 +828,8 @@  d10 :: QuasiQuoter d10 = QuasiQuoter-    { quoteExp  = strD10Fail >=> lift-    , quotePat  = strD10Fail >=> d10Pat+    { quoteExp  = strD10Fail >=> d10Exp'+    , quotePat  = strD10Fail >=> d10Pat'     , quoteType = \_ -> fail "d10 cannot be used in a type context"     , quoteDec  = \_ -> fail "d10 cannot be used in a declaration context"     }@@ -881,8 +875,8 @@  d10list :: QuasiQuoter d10list = QuasiQuoter-    { quoteExp  = strD10ListFail >=> lift-    , quotePat  = strD10ListFail >=> d10ListPat+    { quoteExp  = strD10ListFail >=> d10ListExp'+    , quotePat  = d10ListPat     , quoteType = \_ -> fail "d10list cannot be used in a type context"     , quoteDec  = \_ -> fail "d10list cannot be used in a declaration context"     }
src/Data/D10/Num.hs view
@@ -1,10 +1,3 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE DeriveLift          #-}-{-# LANGUAGE InstanceSigs        #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell     #-}-{-# LANGUAGE TypeApplications    #-}- -- | Defines a 'D10' type as a newtype for any type with an -- instance of the 'Num' class, where the values are restricted -- to numbers between @'fromInteger' 0@ and @'fromInteger' 9@.@@ -45,7 +38,6 @@     , strD10Maybe     , strD10Either     , strD10Fail-    , isD10Str      -- * Converting between [D10] and String     , strD10ListMaybe@@ -92,20 +84,15 @@ import Control.Monad.Fail (MonadFail (fail)) import Data.Char          (chr, ord) import Data.Monoid        (Endo (..))-import GHC.Generics       (Generic) import Numeric.Natural    (Natural) import Prelude            hiding (fail, (+), (-), (*))  import qualified Prelude as P  -- template-haskell+import Language.Haskell.TH.Lib    (litP, integerL) import Language.Haskell.TH.Quote  (QuasiQuoter (..))-import Language.Haskell.TH.Syntax (Exp (..), Lift (lift), Lit (..), Pat (..), Q)---- $setup--- >>> :set -XQuasiQuotes--- >>> :set -XTemplateHaskell--- >>> :set -fno-warn-overlapping-patterns+import Language.Haskell.TH.Syntax (Exp (..), Lift, Pat (..), Q)  --------------------------------------------------- @@ -363,7 +350,7 @@ -- in the string are within the range @'0'@ to @'9'@, or produce -- 'Nothing' otherwise. ----- @'Data.D10.Predicate.isD10Str' x = 'Data.Maybe.isJust' ('strD10ListMaybe' x)@+-- @'Data.D10.Predicate.isD10ListStr' x = 'Data.Maybe.isJust' ('strD10ListMaybe' x)@ -- -- 'strD10ListFail' is a more general version of this function. --@@ -735,9 +722,12 @@ -- You may also be interested in 'd10', a quasi-quoter which -- does something similar. -d10Exp :: forall a b. (Integral b, Lift a, Num a) => b -> Q Exp-d10Exp = integralD10Fail >=> (lift :: D10 a -> Q Exp)+d10Exp :: Integer -> Q Exp+d10Exp = integerD10Fail >=> d10Exp' +d10Exp' :: D10 Integer -> Q Exp+d10Exp' (D10_Unsafe x) = [| D10_Unsafe (fromInteger x) |]+ -- | Produces an expression of type @['D10' a]@ that can be used -- in a Template Haskell splice. --@@ -758,9 +748,12 @@ -- You may also be interested in 'd10list', a quasi-quoter which -- does something similar. -d10ListExp :: forall a. (Lift a, Num a) => String -> Q Exp-d10ListExp = strD10ListFail >=> (lift :: [D10 a] -> Q Exp)+d10ListExp :: String -> Q Exp+d10ListExp = strD10ListFail >=> d10ListExp' +d10ListExp' :: [D10 Integer] -> Q Exp+d10ListExp' xs = [| xs |]+ ---------------------------------------------------  -- | Produces a pattern that can be used in a splice@@ -768,37 +761,42 @@ -- -- >>> :{ --       case (charD10Maybe '5') of---         Just $(d10Pat [d10|4|]) -> "A"---         Just $(d10Pat [d10|5|]) -> "B"---         _                       -> "C"+--         Just $(d10Pat 4) -> "A"+--         Just $(d10Pat 5) -> "B"+--         _                -> "C" -- >>> :} -- "B" -- -- You may wish to use the 'd10' quasi-quoter instead. -d10Pat :: Integral a => D10 a -> Q Pat-d10Pat x =-    return (ConP 'D10_Unsafe [LitP (IntegerL (d10Integer x))])+d10Pat :: Integer -> Q Pat+d10Pat = integerD10Fail >=> d10Pat' +d10Pat' :: D10 Integer -> Q Pat+d10Pat' (D10_Unsafe x) = [p| D10_Unsafe $(litP $ integerL x) |]++d10Pat'' :: Integral a => D10 a -> Q Pat+d10Pat'' (D10_Unsafe x) = [p| D10_Unsafe $(litP $ integerL $ toInteger x) |]+ -- | Produces a pattern that can be used in a splice -- to match a particular list of @'D10' a@ values. -- -- >>> :{ --       case (strD10ListMaybe "56") of---         Just $(d10ListPat [d10list|42|]) -> "A"---         Just $(d10ListPat [d10list|56|]) -> "B"---         _                                -> "C"+--         Just $(d10ListPat "42") -> "A"+--         Just $(d10ListPat "56") -> "B"+--         _                       -> "C" -- >>> :} -- "B" -- -- You may wish to use the 'd10list' quasi-quoter instead. -d10ListPat :: Integral a => [D10 a] -> Q Pat-d10ListPat xs =-  do-    pats <- traverse d10Pat xs-    return (ListP pats)+d10ListPat :: String -> Q Pat+d10ListPat = strD10ListFail >=> d10ListPat' +d10ListPat' :: [D10 Integer] -> Q Pat+d10ListPat' = foldr (\x p -> [p| $(d10Pat'' x) : $(p) |]) [p| [] |]+ ---------------------------------------------------  -- | A single base-10 digit.@@ -839,10 +837,10 @@ -- ... d10 must be between 0 and 9 -- ... -d10 :: forall a. (Lift a, Integral a) => QuasiQuoter+d10 :: QuasiQuoter d10 = QuasiQuoter-    { quoteExp  = strD10Fail >=> (lift :: D10 a -> Q Exp)-    , quotePat  = strD10Fail >=> d10Pat @a+    { quoteExp  = strD10Fail >=> d10Exp'+    , quotePat  = strD10Fail >=> d10Pat'     , quoteType = \_ -> fail "d10 cannot be used in a type context"     , quoteDec  = \_ -> fail "d10 cannot be used in a declaration context"     }@@ -886,10 +884,10 @@ -- ... d10 must be between 0 and 9 -- ... -d10list :: forall a. (Lift a, Integral a) => QuasiQuoter+d10list :: QuasiQuoter d10list = QuasiQuoter-    { quoteExp  = strD10ListFail >=> (lift :: [D10 a] -> Q Exp)-    , quotePat  = strD10ListFail >=> d10ListPat @a+    { quoteExp  = strD10ListFail >=> d10ListExp'+    , quotePat  = strD10ListFail >=> d10ListPat'     , quoteType = \_ -> fail "d10list cannot be used in a type context"     , quoteDec  = \_ -> fail "d10list cannot be used in a declaration context"     }
src/Data/D10/Predicate.hs view
@@ -1,45 +1,37 @@ -- | Functions to test whether values of various -- types represent digits in the range /0/ to /9/.- module Data.D10.Predicate where -import Numeric.Natural+import Numeric.Natural (Natural)  -- | Determines whether a 'Char' is in the range @'0'@ to @'9'@.- isD10Char :: Char -> Bool isD10Char x = x >= '0' && x <= '9'  -- | Determines whether a 'String' consists of a single character -- and that character is within the range @'0'@ to @'9'@.- isD10Str :: String -> Bool isD10Str [x] = isD10Char x isD10Str _   = False  -- | Determines whether a 'String' consists entirely of characters -- that are within the range @'0'@ to @'9'@.- isD10ListStr :: String -> Bool isD10ListStr = all isD10Char  -- | Determines whether a 'Natural' is in the range 0 to 9.- isD10Nat :: Natural -> Bool isD10Nat x = x <= 9  -- | Determines whether an 'Integer' is in the range 0 to 9.- isD10Integer :: Integer -> Bool isD10Integer x = x >= 0 && x <= 9  -- | Determines whether an 'Int' is in the range 0 to 9.- isD10Int :: Int -> Bool isD10Int x = x >= 0 && x <= 9  -- | Determines whether a number whose type has an 'Integral' -- instance is in the range 0 to 9.- isD10Integral :: Integral a => a -> Bool isD10Integral x = isD10Integer (toInteger x)
src/Data/D10/Safe.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE DeriveLift       #-}-{-# LANGUAGE TemplateHaskell  #-}-{-# LANGUAGE TypeApplications #-}- -- | Defines a 'D10' type as -- @'D0' | 'D1' | 'D2' | 'D3' | 'D4' | 'D5' | 'D6' | 'D7' | 'D8' | 'D9'@. --@@ -24,15 +20,12 @@     -- $enum      -- * Quasi-quoters-    , d10     , d10list      -- * Splice expressions-    , d10Exp     , d10ListExp      -- * Splice patterns-    , d10Pat     , d10ListPat      -- * Converting between D10 and Char@@ -85,13 +78,10 @@      ) where -import Data.D10.Predicate- -- base import Control.Monad      ((>=>)) import Control.Monad.Fail (MonadFail (fail))-import Data.Char          (chr, ord)-import Data.Monoid        (Endo (..))+import Data.Data          (Data) import GHC.Generics       (Generic) import Numeric.Natural    (Natural) import Prelude            hiding (fail, (+), (-), (*))@@ -100,12 +90,7 @@  -- template-haskell import Language.Haskell.TH.Quote  (QuasiQuoter (..))-import Language.Haskell.TH.Syntax (Exp (..), Lift (lift), Lit (..), Pat (..), Q)---- $setup--- >>> :set -XQuasiQuotes--- >>> :set -XTemplateHaskell--- >>> :set -fno-warn-overlapping-patterns+import Language.Haskell.TH.Syntax (Exp (..), Lift, Pat (..), Q, dataToPatQ)  --------------------------------------------------- @@ -122,7 +107,7 @@     | D7  -- ^ Seven     | D8  -- ^ Eight     | D9  -- ^ Nine-    deriving (Bounded, Enum, Eq, Lift, Ord, Show)+    deriving (Bounded, Enum, Eq, Lift, Ord, Show, Data, Generic)  -- $bounded -- ==== Bounded@@ -354,7 +339,7 @@ -- in the string are within the range @'0'@ to @'9'@, or produce -- 'Nothing' otherwise. ----- @'Data.D10.Predicate.isD10Str' x = 'Data.Maybe.isJust' ('strD10ListMaybe' x)@+-- @'Data.D10.Predicate.isD10ListStr' x = 'Data.Maybe.isJust' ('strD10ListMaybe' x)@ -- -- 'strD10ListFail' is a more general version of this function. --@@ -750,23 +735,6 @@  --------------------------------------------------- --- | Produces an expression of type 'D10' that can be used--- in a Template Haskell splice.------ >>> $(d10Exp 5)--- D5------ >>> $(d10Exp 12)--- ...--- ... d10 must be between 0 and 9--- ...------ You may also be interested in 'd10', a quasi-quoter which--- does something similar.--d10Exp :: Integral a => a -> Q Exp-d10Exp = integralD10Fail >=> (lift :: D10 -> Q Exp)- -- | Produces an expression of type @['D10']@ that can be used -- in a Template Haskell splice. --@@ -788,114 +756,43 @@ -- does something similar.  d10ListExp :: String -> Q Exp-d10ListExp = strD10ListFail >=> (lift :: [D10] -> Q Exp)+d10ListExp = strD10ListFail >=> d10ListExp' ----------------------------------------------------+d10ListExp' :: [D10] -> Q Exp+d10ListExp' x = [| x |] --- | Produces a pattern that can be used in a splice--- to match a particular 'D10' value.------ >>> :{---       case (charD10Maybe '5') of---         Just $(d10Pat D4) -> "A"---         Just $(d10Pat D5) -> "B"---         _                 -> "C"--- >>> :}--- "B"------ You are unlikely to write any code that resembles this example,--- since you can just write @D4@ instead of @$(d10Pat D4)@.--- Rather, this function exists to help implement other things--- related to Template Haskell, such as 'd10ListPat' and 'd10'.+---------------------------------------------------  d10Pat :: D10 -> Q Pat-d10Pat x =-    case x of-        D0 -> [p| D0 |]-        D1 -> [p| D1 |]-        D2 -> [p| D2 |]-        D3 -> [p| D3 |]-        D4 -> [p| D4 |]-        D5 -> [p| D5 |]-        D6 -> [p| D6 |]-        D7 -> [p| D7 |]-        D8 -> [p| D8 |]-        D9 -> [p| D9 |]+d10Pat = dataToPatQ (const Nothing)  -- | Produces a pattern that can be used in a splice -- to match a particular list of 'D10' values. -- -- >>> :{---       case (strD10ListMaybe "56") of---         Just $(d10ListPat [D4, D2]) -> "A"---         Just $(d10ListPat [D5, D6]) -> "B"---         _                                -> "C"+--       case [D5, D6] of+--         $(d10ListPat "42") -> "A"+--         $(d10ListPat "56") -> "B"+--         _                  -> "C" -- >>> :} -- "B" ----- You are unlikely to write any code that resembles this example,--- since you can just write @[D4, D2]@ instead of @$(d10Pat [D4, D2])@.--- Rather, this function exists to help implement other things--- related to Template Haskell, such as 'd10list'.+-- You may also be interested in 'd10list', a quasi-quoter which+-- does something similar. -d10ListPat :: [D10] -> Q Pat-d10ListPat xs =+d10ListPat :: String -> Q Pat+d10ListPat = strD10ListFail >=> \xs ->   do     pats <- traverse d10Pat xs     return (ListP pats) -------------------------------------------------------- | A single base-10 digit.------ This isn't very useful, since you can just write 'D5'--- instead of '[d10|5|]'. It is included only for completeness,--- because each of the modules "Data.D10.Char" and "Data.D10.Num"--- defines a similar quasi-quoter.------ This quasi-quoter, when used as an expression, produces a--- value of type 'D10'.------ >>> [d10|5|]--- D5------ >>> [d10|a|]--- ...--- ... d10 must be between 0 and 9--- ...------ >>> [d10|58|]--- ...--- ... d10 must be a single character--- ...------ This quasi-quoter can also be used as a pattern.------ >>> :{---       case (charD10Maybe '5') of---         Just [d10|4|] -> "A"---         Just [d10|5|] -> "B"---         _             -> "C"--- >>> :}--- "B"------ >>> :{---       case (charD10Maybe '5') of---         Just [d10|x|] -> "A"---         Just [d10|5|] -> "B"---         _             -> "C"--- >>> :}--- ...--- ... d10 must be between 0 and 9--- ...+d10ListPat' :: [D10] -> Q Pat+d10ListPat' xs =+  do+    pats <- traverse d10Pat xs+    return (ListP pats) -d10 :: QuasiQuoter-d10 = QuasiQuoter-    { quoteExp  = strD10Fail >=> lift-    , quotePat  = strD10Fail >=> d10Pat-    , quoteType = \_ -> fail "d10 cannot be used in a type context"-    , quoteDec  = \_ -> fail "d10 cannot be used in a declaration context"-    }+---------------------------------------------------  -- | A list of base-10 digits. --@@ -919,7 +816,7 @@ -- This quasi-quoter can also be used as a pattern. -- -- >>> :{---       case [d10list|56|] of+--       case [D5, D6] of --         [d10list|41|] -> "A" --         [d10list|56|] -> "B" --         _             -> "C"@@ -927,7 +824,7 @@ -- "B" -- -- >>> :{---       case [d10list|56|] of+--       case [D5, D6] of --         [d10list|4x|] -> "A" --         [d10list|56|] -> "B" --         _             -> "C"@@ -938,8 +835,8 @@  d10list :: QuasiQuoter d10list = QuasiQuoter-    { quoteExp  = strD10ListFail >=> lift-    , quotePat  = strD10ListFail >=> d10ListPat+    { quoteExp  = strD10ListFail >=> d10ListExp'+    , quotePat  = strD10ListFail >=> d10ListPat'     , quoteType = \_ -> fail "d10list cannot be used in a type context"     , quoteDec  = \_ -> fail "d10list cannot be used in a declaration context"     }
+ test/AssertQFails.hs view
@@ -0,0 +1,15 @@+module AssertQFails where++import Hedgehog++import Control.Exception (try, SomeException)+import Control.Monad.IO.Class (liftIO)+import Language.Haskell.TH (runQ, Q)++qFails :: Show a => Q a -> PropertyT IO ()+qFails (q :: Q a) =+  do+    result <- liftIO (try (runQ q) :: IO (Either SomeException a))+    case result of+        Left _ -> success+        Right _ -> failure
+ test/Fallible.hs view
@@ -0,0 +1,10 @@+module Fallible where++import Control.Monad.Fail (MonadFail (fail))+import Prelude hiding (fail)++newtype Fallible a = Fallible (Either String a)+    deriving newtype (Functor, Applicative, Monad, Eq, Show)++instance MonadFail Fallible where+    fail = Fallible . Left
+ test/char.hs view
@@ -0,0 +1,247 @@+import Prelude hiding (fail, (+), (-), (*))++import Data.D10.Char+import qualified Data.D10.Predicate as Predicate++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Control.Applicative ((<|>))+import Control.Monad (when)+import Control.Monad.Fail (MonadFail (fail))+import Data.Maybe (isJust)+import System.Exit (exitFailure)++import AssertQFails (qFails)+import Fallible (Fallible)++main :: IO ()+main =+  do+    ok <- checkParallel $$(discover)+    when (not ok) exitFailure++genD10 :: Gen D10+genD10 = Gen.enumBounded++prop_bounds_examples :: Property+prop_bounds_examples = withTests 1 $ property $ do+    minBound === [d10|0|]+    maxBound === [d10|9|]++prop_enumeration_examples :: Property+prop_enumeration_examples = withTests 1 $ property $ do+    [ [d10|5|] .. ]           === [d10list|56789|]+    [ [d10|4|] .. [d10|7|] ]  === [d10list|4567|]+    [ [d10|5|], [d10|4|] .. ] === [d10list|543210|]+    [ [d10|1|], [d10|3|] .. ] === [d10list|13579|]+    [ minBound .. maxBound ]  === [d10list|0123456789|]++prop_lift_examples :: Property+prop_lift_examples = withTests 1 $ property $ do+    d10Char    [d10|7|] === '7'+    d10Str     [d10|7|] === "7"+    d10Nat     [d10|7|] ===  7+    d10Integer [d10|7|] ===  7+    d10Int     [d10|7|] ===  7+    d10Num     [d10|7|] ===  (7 :: Integer)++prop_d10Str :: Property+prop_d10Str = property $ do+    x <- forAll genD10+    d10Str x === [d10Char x]++prop_mod_examples :: Property+prop_mod_examples = withTests 1 $ property $ do+    natMod10       56  === [d10|6|]+    integerMod10   56  === [d10|6|]+    integerMod10 (-56) === [d10|4|]+    intMod10       56  === [d10|6|]+    intMod10     (-56) === [d10|4|]++    integralMod10   (56  :: Integer) === [d10|6|]+    integralMod10 ((-56) :: Integer) === [d10|4|]++prop_d10Maybe_examples :: Property+prop_d10Maybe_examples = withTests 1 $ property $ do+    charD10Maybe '5' === Just [d10|5|]+    charD10Maybe 'a' === Nothing+    strD10Maybe "5"  === Just [d10|5|]+    strD10Maybe "a"  === Nothing+    strD10Maybe "58" === Nothing++prop_isJust_string :: Property+prop_isJust_string = property $ do+    x <- forAll $ Gen.string (Range.linear 0 5) (Gen.digit <|> Gen.alpha)+    Predicate.isD10Str     x === isJust (strD10Maybe x)+    Predicate.isD10ListStr x === isJust (strD10ListMaybe x)++prop_isJust_nat :: Property+prop_isJust_nat = property $ do+    x <- forAll $ Gen.integral (Range.linear 0 20)+    Predicate.isD10Nat x === isJust (natD10Maybe x)++prop_d10ListMaybe_examples :: Property+prop_d10ListMaybe_examples = withTests 1 $ property $ do+    strD10ListMaybe "5"  === Just [d10list|5|]+    strD10ListMaybe "a"  === Nothing+    strD10ListMaybe "58" === Just [d10list|58|]++prop_natD10Maybe_examples :: Property+prop_natD10Maybe_examples = withTests 1 $ property $ do+    natD10Maybe  5 === Just [d10|5|]+    natD10Maybe 12 === Nothing++prop_isJust_integer :: Property+prop_isJust_integer = property $ do+    x <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Integer x === isJust (integerD10Maybe x)++prop_integerD10Maybe_examples :: Property+prop_integerD10Maybe_examples = withTests 1 $ property $ do+    integerD10Maybe   5  === Just [d10|5|]+    integerD10Maybe  12  === Nothing+    integerD10Maybe (-5) === Nothing++prop_isJust_int :: Property+prop_isJust_int = withTests 1 $ property $ do+    x <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Int x === isJust (intD10Maybe x)++prop_intD10Maybe_examples :: Property+prop_intD10Maybe_examples = withTests 1 $ property $ do+    intD10Maybe   5  === Just [d10|5|]+    intD10Maybe  12  === Nothing+    intD10Maybe (-5) === Nothing++prop_isJust_integral :: Property+prop_isJust_integral = property $ do+    x <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Integral (x :: Integer) === isJust (integerD10Maybe x)++prop_integralD10Maybe_examples :: Property+prop_integralD10Maybe_examples = withTests 1 $ property $ do+    integralD10Maybe (   5  :: Integer ) === Just [d10|5|]+    integralD10Maybe (  12  :: Integer ) === Nothing+    integralD10Maybe ( (-5) :: Integer ) === Nothing++prop_charD10Either_examples :: Property+prop_charD10Either_examples = withTests 1 $ property $ do+    charD10Either '5' === Right [d10|5|]+    charD10Either 'a' === Left "d10 must be between 0 and 9"++prop_strD10Either_examples :: Property+prop_strD10Either_examples = withTests 1 $ property $ do+    strD10Either  "5" === Right [d10|5|]+    strD10Either  "a" === Left "d10 must be between 0 and 9"+    strD10Either "58" === Left "d10 must be a single character"++prop_strD10ListEither_examples :: Property+prop_strD10ListEither_examples = withTests 1 $ property $ do+    strD10ListEither  "5" === Right [d10list|5|]+    strD10ListEither  "a" === Left "d10 must be between 0 and 9"+    strD10ListEither "58" === Right [d10list|58|]++prop_natD10ListEither_examples :: Property+prop_natD10ListEither_examples = withTests 1 $ property $ do+    natD10Either  5 === Right [d10|5|]+    natD10Either 12 === Left "d10 must be less than 10"++prop_integerD10ListEither_examples :: Property+prop_integerD10ListEither_examples = withTests 1 $ property $ do+    integerD10Either   5  === Right [d10|5|]+    integerD10Either  12  === Left "d10 must be between 0 and 9"+    integerD10Either (-5) === Left "d10 must be between 0 and 9"++prop_intD10ListEither_examples :: Property+prop_intD10ListEither_examples = withTests 1 $ property $ do+    intD10Either   5  === Right [d10|5|]+    intD10Either  12  === Left "d10 must be between 0 and 9"+    intD10Either (-5) === Left "d10 must be between 0 and 9"++prop_integralD10ListEither_examples :: Property+prop_integralD10ListEither_examples = withTests 1 $ property $ do+    integralD10Either   (5  :: Integer) === Right [d10|5|]+    integralD10Either  (12  :: Integer) === Left "d10 must be between 0 and 9"+    integralD10Either ((-5) :: Integer) === Left "d10 must be between 0 and 9"++prop_charD10Fail_examples :: Property+prop_charD10Fail_examples = withTests 1 $ property $ do+    (charD10Fail '5' :: Fallible D10) === return [d10|5|]+    (charD10Fail 'a' :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_strD10Fail_examples :: Property+prop_strD10Fail_examples = withTests 1 $ property $ do+    (strD10Fail  "5" :: Fallible D10) === return [d10|5|]+    (strD10Fail  "a" :: Fallible D10) === fail "d10 must be between 0 and 9"+    (strD10Fail "58" :: Fallible D10) === fail "d10 must be a single character"++prop_strD10ListFail_examples :: Property+prop_strD10ListFail_examples = withTests 1 $ property $ do+    (strD10ListFail  "5" :: Fallible [D10]) === return [d10list|5|]+    (strD10ListFail  "a" :: Fallible [D10]) === fail "d10 must be between 0 and 9"+    (strD10ListFail "58" :: Fallible [D10]) === return [d10list|58|]++prop_natD10Fail_examples :: Property+prop_natD10Fail_examples = withTests 1 $ property $ do+    (natD10Fail  5 :: Fallible D10) === return [d10|5|]+    (natD10Fail 12 :: Fallible D10) === fail "d10 must be less than 10"++prop_integerD10Fail_examples :: Property+prop_integerD10Fail_examples = withTests 1 $ property $ do+    (integerD10Fail   5  :: Fallible D10) === return [d10|5|]+    (integerD10Fail  12  :: Fallible D10) === fail "d10 must be between 0 and 9"+    (integerD10Fail (-5) :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_intD10Fail_examples :: Property+prop_intD10Fail_examples = withTests 1 $ property $ do+    (intD10Fail   5  :: Fallible D10) === return [d10|5|]+    (intD10Fail  12  :: Fallible D10) === fail "d10 must be between 0 and 9"+    (intD10Fail (-5) :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_integralD10Fail_examples :: Property+prop_integralD10Fail_examples = withTests 1 $ property $ do+    (integralD10Fail   (5  :: Integer) :: Fallible D10) === return [d10|5|]+    (integralD10Fail  (12  :: Integer) :: Fallible D10) === fail "d10 must be between 0 and 9"+    (integralD10Fail ((-5) :: Integer) :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_spliceExp_examples :: Property+prop_spliceExp_examples = withTests 1 $ property $ do+    d10Nat $(d10Exp 5) === 5+    qFails (d10Exp 12)+    (d10Nat <$> $(d10ListExp "")) === []+    (d10Nat <$> $(d10ListExp "5")) === [5]+    (d10Nat <$> $(d10ListExp "58")) === [5,8]++prop_splicePat_examples :: Property+prop_splicePat_examples = withTests 1 $ property $ do+    "B" === case (charD10Maybe '5') of+        Just $(d10Pat 4) -> "A"+        Just $(d10Pat 5) -> "B"+        _                -> "C"+    qFails (d10Pat 12)+    "B" === case (strD10ListMaybe "56") of+        Just $(d10ListPat "42") -> "A"+        Just $(d10ListPat "56") -> "B"+        _                       -> "C"++prop_qqPat_examples :: Property+prop_qqPat_examples = withTests 1 $ property $ do+    "B" === case (charD10Maybe '5') of+        Just [d10|4|] -> "A"+        Just [d10|5|] -> "B"+        _             -> "C"+    "B" === case [d10list|56|] of+        [d10list|41|] -> "A"+        [d10list|56|] -> "B"+        _             -> "C"++prop_arithmetic_examples :: Property+prop_arithmetic_examples = withTests 1 $ property $ do+    [d10|2|] + [d10|3|] === [d10|5|]+    [d10|6|] + [d10|7|] === [d10|3|]+    [d10|7|] - [d10|5|] === [d10|2|]+    [d10|3|] - [d10|7|] === [d10|6|]+    [d10|2|] * [d10|4|] === [d10|8|]+    [d10|7|] * [d10|8|] === [d10|6|]
− test/doctest.hs
@@ -1,11 +0,0 @@-import           Test.DocTest--main :: IO ()-main =-  doctest-    [ "-isrc"-    , "src/Data/D10/Char.hs"-    , "src/Data/D10/Num.hs"-    , "src/Data/D10/Predicate.hs"-    , "src/Data/D10/Safe.hs"-    ]
+ test/num.hs view
@@ -0,0 +1,250 @@+import Prelude hiding (fail, (+), (-), (*))++import Data.D10.Num+import qualified Data.D10.Predicate as Predicate++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Control.Applicative ((<|>))+import Control.Monad (when)+import Control.Monad.Fail (MonadFail (fail))+import Data.Int (Int32)+import Data.Maybe (isJust)+import Data.Word (Word64)+import System.Exit (exitFailure)++import AssertQFails (qFails)+import Fallible (Fallible)++main :: IO ()+main =+  do+    ok <- checkParallel $$(discover)+    when (not ok) exitFailure++genD10 :: Integral a => Gen (D10 a)+genD10 = Gen.enumBounded++prop_bounds_examples :: Property+prop_bounds_examples = withTests 1 $ property $ do+    minBound === ([d10|0|] :: D10 Int)+    maxBound === ([d10|9|] :: D10 Int)++prop_enumeration_examples :: Property+prop_enumeration_examples = withTests 1 $ property $ do+    [ [d10|5|] .. ]           === ([d10list|56789|]      :: [D10 Integer])+    [ [d10|4|] .. [d10|7|] ]  === ([d10list|4567|]       :: [D10 Integer])+    [ [d10|5|], [d10|4|] .. ] === ([d10list|543210|]     :: [D10 Integer])+    [ [d10|1|], [d10|3|] .. ] === ([d10list|13579|]      :: [D10 Integer])+    [ minBound .. maxBound ]  === ([d10list|0123456789|] :: [D10 Integer])++prop_lift_examples :: Property+prop_lift_examples = withTests 1 $ property $ do+    d10Char    ([d10|7|] :: D10 Integer) === '7'+    d10Str     ([d10|7|] :: D10 Integer) === "7"+    d10Nat     ([d10|7|] :: D10 Integer) ===  7+    d10Integer ([d10|7|] :: D10 Integer) ===  7+    d10Int     ([d10|7|] :: D10 Integer) ===  7+    d10Num     ([d10|7|] :: D10 Integer) ===  (7 :: Integer)++prop_d10Str :: Property+prop_d10Str = property $ do+    x :: D10 Integer <- forAll genD10+    d10Str x === [d10Char x]++prop_mod_examples :: Property+prop_mod_examples = withTests 1 $ property $ do+    natMod10       56  === ([d10|6|] :: D10 Integer)+    integerMod10   56  === ([d10|6|] :: D10 Integer)+    integerMod10 (-56) === ([d10|4|] :: D10 Integer)+    intMod10       56  === ([d10|6|] :: D10 Integer)+    intMod10     (-56) === ([d10|4|] :: D10 Integer)++    integralMod10   (56  :: Integer) === ([d10|6|] :: D10 Integer)+    integralMod10 ((-56) :: Integer) === ([d10|4|] :: D10 Integer)++prop_d10Maybe_examples :: Property+prop_d10Maybe_examples = withTests 1 $ property $ do+    charD10Maybe '5' === (Just [d10|5|] :: Maybe (D10 Integer))+    charD10Maybe 'a' === (Nothing       :: Maybe (D10 Integer))+    strD10Maybe "5"  === (Just [d10|5|] :: Maybe (D10 Integer))+    strD10Maybe "a"  === (Nothing       :: Maybe (D10 Integer))+    strD10Maybe "58" === (Nothing       :: Maybe (D10 Integer))++prop_isJust_string :: Property+prop_isJust_string = property $ do+    x <- forAll $ Gen.string (Range.linear 0 5) (Gen.digit <|> Gen.alpha)+    Predicate.isD10Str     x === isJust (strD10Maybe x     :: Maybe (D10 Integer))+    Predicate.isD10ListStr x === isJust (strD10ListMaybe x :: Maybe [D10 Integer])++prop_isJust_nat :: Property+prop_isJust_nat = property $ do+    x <- forAll $ Gen.integral (Range.linear 0 20)+    Predicate.isD10Nat x === isJust (natD10Maybe x :: Maybe (D10 Integer))++prop_d10ListMaybe_examples :: Property+prop_d10ListMaybe_examples = withTests 1 $ property $ do+    strD10ListMaybe "5"  === (Just [d10list|5|]  :: Maybe [D10 Integer])+    strD10ListMaybe "a"  === (Nothing            :: Maybe [D10 Integer])+    strD10ListMaybe "58" === (Just [d10list|58|] :: Maybe [D10 Integer])++prop_natD10Maybe_examples :: Property+prop_natD10Maybe_examples = withTests 1 $ property $ do+    natD10Maybe  5 === (Just [d10|5|] :: Maybe (D10 Integer))+    natD10Maybe 12 === (Nothing       :: Maybe (D10 Integer))++prop_isJust_integer :: Property+prop_isJust_integer = property $ do+    x <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Integer x === isJust (integerD10Maybe x :: Maybe (D10 Integer))++prop_integerD10Maybe_examples :: Property+prop_integerD10Maybe_examples = withTests 1 $ property $ do+    integerD10Maybe   5  === (Just [d10|5|] :: Maybe (D10 Integer))+    integerD10Maybe  12  === (Nothing       :: Maybe (D10 Integer))+    integerD10Maybe (-5) === (Nothing       :: Maybe (D10 Integer))++prop_isJust_int :: Property+prop_isJust_int = withTests 1 $ property $ do+    x <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Int x === isJust (intD10Maybe x :: Maybe (D10 Integer))++prop_intD10Maybe_examples :: Property+prop_intD10Maybe_examples = withTests 1 $ property $ do+    intD10Maybe   5  === (Just [d10|5|] :: Maybe (D10 Integer))+    intD10Maybe  12  === (Nothing       :: Maybe (D10 Integer))+    intD10Maybe (-5) === (Nothing       :: Maybe (D10 Integer))++prop_isJust_integral :: Property+prop_isJust_integral = property $ do+    x <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Integral (x :: Integer) === isJust (integerD10Maybe x :: Maybe (D10 Integer))++prop_integralD10Maybe_examples :: Property+prop_integralD10Maybe_examples = withTests 1 $ property $ do+    integralD10Maybe (   5  :: Integer ) === (Just [d10|5|] :: Maybe (D10 Integer))+    integralD10Maybe (  12  :: Integer ) === (Nothing       :: Maybe (D10 Integer))+    integralD10Maybe ( (-5) :: Integer ) === (Nothing       :: Maybe (D10 Integer))++prop_charD10Either_examples :: Property+prop_charD10Either_examples = withTests 1 $ property $ do+    charD10Either '5' === (Right [d10|5|]                     :: Either String (D10 Integer) )+    charD10Either 'a' === (Left "d10 must be between 0 and 9" :: Either String (D10 Integer) )++prop_strD10Either_examples :: Property+prop_strD10Either_examples = withTests 1 $ property $ do+    strD10Either  "5" === (Right [d10|5|]                        :: Either String (D10 Integer))+    strD10Either  "a" === (Left "d10 must be between 0 and 9"    :: Either String (D10 Integer))+    strD10Either "58" === (Left "d10 must be a single character" :: Either String (D10 Integer))++prop_strD10ListEither_examples :: Property+prop_strD10ListEither_examples = withTests 1 $ property $ do+    strD10ListEither  "5" === (Right [d10list|5|]                 :: Either String [D10 Integer])+    strD10ListEither  "a" === (Left "d10 must be between 0 and 9" :: Either String [D10 Integer])+    strD10ListEither "58" === (Right [d10list|58|]                :: Either String [D10 Integer])++prop_natD10ListEither_examples :: Property+prop_natD10ListEither_examples = withTests 1 $ property $ do+    natD10Either  5 === (Right [d10|5|]                  :: Either String (D10 Integer))+    natD10Either 12 === (Left "d10 must be less than 10" :: Either String (D10 Integer))++prop_integerD10ListEither_examples :: Property+prop_integerD10ListEither_examples = withTests 1 $ property $ do+    integerD10Either   5  === (Right [d10|5|]                     :: Either String (D10 Integer))+    integerD10Either  12  === (Left "d10 must be between 0 and 9" :: Either String (D10 Integer))+    integerD10Either (-5) === (Left "d10 must be between 0 and 9" :: Either String (D10 Integer))++prop_intD10ListEither_examples :: Property+prop_intD10ListEither_examples = withTests 1 $ property $ do+    intD10Either   5  === (Right [d10|5|]                     :: Either String (D10 Integer))+    intD10Either  12  === (Left "d10 must be between 0 and 9" :: Either String (D10 Integer))+    intD10Either (-5) === (Left "d10 must be between 0 and 9" :: Either String (D10 Integer))++prop_integralD10ListEither_examples :: Property+prop_integralD10ListEither_examples = withTests 1 $ property $ do+    integralD10Either   (5  :: Integer) === (Right [d10|5|]                     :: Either String (D10 Integer))+    integralD10Either  (12  :: Integer) === (Left "d10 must be between 0 and 9" :: Either String (D10 Integer))+    integralD10Either ((-5) :: Integer) === (Left "d10 must be between 0 and 9" :: Either String (D10 Integer))++prop_charD10Fail_examples :: Property+prop_charD10Fail_examples = withTests 1 $ property $ do+    (charD10Fail '5' :: Fallible (D10 Int)) === return [d10|5|]+    (charD10Fail 'a' :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"++prop_strD10Fail_examples :: Property+prop_strD10Fail_examples = withTests 1 $ property $ do+    (strD10Fail  "5" :: Fallible (D10 Int)) === return [d10|5|]+    (strD10Fail  "a" :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"+    (strD10Fail "58" :: Fallible (D10 Int)) === fail "d10 must be a single character"++prop_strD10ListFail_examples :: Property+prop_strD10ListFail_examples = withTests 1 $ property $ do+    (strD10ListFail  "5" :: Fallible [D10 Int]) === return [d10list|5|]+    (strD10ListFail  "a" :: Fallible [D10 Int]) === fail "d10 must be between 0 and 9"+    (strD10ListFail "58" :: Fallible [D10 Int]) === return [d10list|58|]++prop_natD10Fail_examples :: Property+prop_natD10Fail_examples = withTests 1 $ property $ do+    (natD10Fail  5 :: Fallible (D10 Int)) === return [d10|5|]+    (natD10Fail 12 :: Fallible (D10 Int)) === fail "d10 must be less than 10"++prop_integerD10Fail_examples :: Property+prop_integerD10Fail_examples = withTests 1 $ property $ do+    (integerD10Fail   5  :: Fallible (D10 Int)) === return [d10|5|]+    (integerD10Fail  12  :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"+    (integerD10Fail (-5) :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"++prop_intD10Fail_examples :: Property+prop_intD10Fail_examples = withTests 1 $ property $ do+    (intD10Fail   5  :: Fallible (D10 Int)) === return [d10|5|]+    (intD10Fail  12  :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"+    (intD10Fail (-5) :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"++prop_integralD10Fail_examples :: Property+prop_integralD10Fail_examples = withTests 1 $ property $ do+    (integralD10Fail   (5  :: Integer) :: Fallible (D10 Int)) === return [d10|5|]+    (integralD10Fail  (12  :: Integer) :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"+    (integralD10Fail ((-5) :: Integer) :: Fallible (D10 Int)) === fail "d10 must be between 0 and 9"++prop_spliceExp_examples :: Property+prop_spliceExp_examples = withTests 1 $ property $ do+    d10Nat ($(d10Exp 5) :: D10 Word64) === 5+    qFails (d10Exp 12)+    map d10Nat ($(d10ListExp "")   :: [D10 Word]) === []+    map d10Nat ($(d10ListExp "5")  :: [D10 Word]) === [5]+    map d10Nat ($(d10ListExp "58") :: [D10 Word]) === [5,8]++prop_splicePat_examples :: Property+prop_splicePat_examples = withTests 1 $ property $ do+    "B" === case (charD10Maybe '5') :: Maybe (D10 Int) of+        Just $(d10Pat 4) -> "A"+        Just $(d10Pat 5) -> "B"+        _                -> "C"+    qFails (d10Pat 12)+    qFails (d10ListPat "ab")++prop_qqPat_examples :: Property+prop_qqPat_examples = withTests 1 $ property $ do+    "B" === case charD10Maybe '5' :: Maybe (D10 Int) of+        Just [d10|4|] -> "A"+        Just [d10|5|] -> "B"+        _             -> "C"+    "B" === case charD10Maybe '5' :: Maybe (D10 Integer) of+        Just [d10|4|] -> "A"+        Just [d10|5|] -> "B"+        _             -> "C"+    "B" === case [d10list|56|] :: [D10 Int32] of+        [d10list|41|] -> "A"+        [d10list|56|] -> "B"+        _             -> "C"++prop_arithmetic_examples :: Property+prop_arithmetic_examples = withTests 1 $ property $ do+    [d10|2|] + [d10|3|] === ([d10|5|] :: D10 Int32)+    [d10|6|] + [d10|7|] === ([d10|3|] :: D10 Int32)+    [d10|7|] - [d10|5|] === ([d10|2|] :: D10 Int32)+    [d10|3|] - [d10|7|] === ([d10|6|] :: D10 Int32)+    [d10|2|] * [d10|4|] === ([d10|8|] :: D10 Int32)+    [d10|7|] * [d10|8|] === ([d10|6|] :: D10 Int32)
+ test/safe.hs view
@@ -0,0 +1,279 @@+import Prelude hiding (fail, (+), (-), (*))++import Data.D10.Safe+import qualified Data.D10.Predicate as Predicate++import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Control.Applicative ((<|>))+import Control.Monad (when)+import Control.Monad.Fail (MonadFail (fail))+import Data.Maybe (isJust)+import System.Exit (exitFailure)++import AssertQFails (qFails)+import Fallible (Fallible)++main :: IO ()+main =+  do+    ok <- checkParallel $$(discover)+    when (not ok) exitFailure++genD10 :: Gen D10+genD10 = Gen.enumBounded++prop_bounds_examples :: Property+prop_bounds_examples = withTests 1 $ property $ do+    minBound === D0+    maxBound === D9++prop_enumeration_examples :: Property+prop_enumeration_examples = withTests 1 $ property $ do+    [ D5 .. ] === [D5,D6,D7,D8,D9]+    [ D4 .. D7 ] === [D4,D5,D6,D7]+    [ D5, D4 .. ] === [D5,D4,D3,D2,D1,D0]+    [ D1, D3 .. ] === [D1,D3,D5,D7,D9]+    [ minBound .. maxBound ] === [D0,D1,D2,D3,D4,D5,D6,D7,D8,D9]++prop_d10Char_examples :: Property+prop_d10Char_examples = withTests 1 $ property $ do+    d10Char D7 === '7'++prop_d10Str :: Property+prop_d10Str = property $ do+    x <- forAll genD10+    d10Str x === [d10Char x]++prop_d10Str_examples :: Property+prop_d10Str_examples = withTests 1 $ property $ do+    d10Str D7 === "7"++prop_d10Nat_examples :: Property+prop_d10Nat_examples = withTests 1 $ property $ do+    d10Nat D7 === 7++prop_d10Integer_examples :: Property+prop_d10Integer_examples = withTests 1 $ property $ do+    d10Integer D7 === 7++prop_d10Int_examples :: Property+prop_d10Int_examples = withTests 1 $ property $ do+    d10Int D7 === 7++prop_d10Num_examples :: Property+prop_d10Num_examples = withTests 1 $ property $ do+    d10Num D7 === (7 :: Integer)++prop_natMod10_examples :: Property+prop_natMod10_examples = withTests 1 $ property $ do+    natMod10 56 === D6++prop_integerMod10_examples :: Property+prop_integerMod10_examples = withTests 1 $ property $ do+    integerMod10 56 === D6+    integerMod10 (-56) === D4++prop_intMod10_examples :: Property+prop_intMod10_examples = withTests 1 $ property $ do+    intMod10 56 === D6+    intMod10 (-56) === D4++prop_integralMod10_examples :: Property+prop_integralMod10_examples = withTests 1 $ property $ do+    integralMod10 (56 :: Integer) === D6+    integralMod10 ((-56) :: Integer) === D4++prop_charD10Maybe :: Property+prop_charD10Maybe = property $ do+    x <- forAll (Gen.digit <|> Gen.alpha)+    Predicate.isD10Char x === isJust (charD10Maybe x)++prop_charD10Maybe_examples :: Property+prop_charD10Maybe_examples = withTests 1 $ property $ do+    charD10Maybe '5' === Just D5+    charD10Maybe 'a' === Nothing++prop_strD10Maybe :: Property+prop_strD10Maybe = property $ do+    x <- forAll $ Gen.string (Range.linear 0 5) (Gen.digit <|> Gen.alpha)+    Predicate.isD10Str x === isJust (strD10Maybe x)++prop_strD10Maybe_examples :: Property+prop_strD10Maybe_examples = withTests 1 $ property $ do+    strD10Maybe "5" === Just D5+    strD10Maybe "a" === Nothing+    strD10Maybe "58" === Nothing++prop_strD10ListMaybe :: Property+prop_strD10ListMaybe = property $ do+    x <- forAll $ Gen.string (Range.linear 0 5) (Gen.digit <|> Gen.alpha)+    Predicate.isD10ListStr x === isJust (strD10ListMaybe x)++prop_strD10ListMaybe_examples :: Property+prop_strD10ListMaybe_examples = withTests 1 $ property $ do+    strD10ListMaybe "5" === Just [D5]+    strD10ListMaybe "a" === Nothing+    strD10ListMaybe "58" === Just [D5,D8]++prop_natD10Maybe :: Property+prop_natD10Maybe = property $ do+    x <- forAll $ Gen.integral (Range.linear 0 20)+    Predicate.isD10Nat x === isJust (natD10Maybe x)++prop_natD10Maybe_examples :: Property+prop_natD10Maybe_examples = withTests 1 $ property $ do+    natD10Maybe 5 === Just D5+    natD10Maybe 12 === Nothing++prop_integerD10Maybe :: Property+prop_integerD10Maybe = property $ do+    x <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Integer x === isJust (integerD10Maybe x)++prop_integerD10Maybe_examples :: Property+prop_integerD10Maybe_examples = withTests 1 $ property $ do+    integerD10Maybe 5 === Just D5+    integerD10Maybe 12 === Nothing+    integerD10Maybe (-5) === Nothing++prop_intD10Maybe :: Property+prop_intD10Maybe = property $ do+    x :: Int <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Int x === isJust (intD10Maybe x)++prop_intD10Maybe_examples :: Property+prop_intD10Maybe_examples = withTests 1 $ property $ do+    intD10Maybe 5 === Just D5+    intD10Maybe 12 === Nothing+    intD10Maybe (-5) === Nothing++prop_integralD10Maybe :: Property+prop_integralD10Maybe = property $ do+    x :: Integer <- forAll $ Gen.integral (Range.linearFrom 0 (-5) 15)+    Predicate.isD10Integer x === isJust (integralD10Maybe x)++prop_integralD10Maybe_examples :: Property+prop_integralD10Maybe_examples = withTests 1 $ property $ do+    integralD10Maybe (5 :: Integer) === Just D5+    integralD10Maybe (12 :: Integer) === Nothing+    integralD10Maybe ((-5) :: Integer) === Nothing++prop_charD10Either_examples :: Property+prop_charD10Either_examples = withTests 1 $ property $ do+    charD10Either '5' === Right D5+    charD10Either 'a' === Left "d10 must be between 0 and 9"++prop_strD10Either_examples :: Property+prop_strD10Either_examples = withTests 1 $ property $ do+    strD10Either "5" === Right D5+    strD10Either "a" === Left "d10 must be between 0 and 9"+    strD10Either "58" === Left "d10 must be a single character"++prop_strD10ListEither_examples :: Property+prop_strD10ListEither_examples = withTests 1 $ property $ do+    strD10ListEither "5" === Right [D5]+    strD10ListEither "a" === Left "d10 must be between 0 and 9"+    strD10ListEither "58" === Right [D5,D8]++prop_natD10Either_examples :: Property+prop_natD10Either_examples = withTests 1 $ property $ do+    natD10Either 5 === Right D5+    natD10Either 12 === Left "d10 must be less than 10"++prop_integerD10Either_examples :: Property+prop_integerD10Either_examples = withTests 1 $ property $ do+    integerD10Either 5 === Right D5+    integerD10Either 12 === Left "d10 must be between 0 and 9"+    integerD10Either (-5) === Left "d10 must be between 0 and 9"++prop_intD10Either_examples :: Property+prop_intD10Either_examples = withTests 1 $ property $ do+    intD10Either 5 === Right D5+    intD10Either 12 === Left "d10 must be between 0 and 9"+    intD10Either (-5) === Left "d10 must be between 0 and 9"++prop_integralD10Either_examples :: Property+prop_integralD10Either_examples = withTests 1 $ property $ do+    integralD10Either (5 :: Integer) === Right D5+    integralD10Either (12 :: Integer) === Left "d10 must be between 0 and 9"+    integralD10Either (-5 :: Integer) === Left "d10 must be between 0 and 9"++prop_charD10Fail_examples :: Property+prop_charD10Fail_examples = withTests 1 $ property $ do+    (charD10Fail '5' :: Fallible D10) === return D5+    (charD10Fail 'a' :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_strD10Fail_examples :: Property+prop_strD10Fail_examples = withTests 1 $ property $ do+    (strD10Fail "5" :: Fallible D10) === return D5+    (strD10Fail "a" :: Fallible D10) === fail "d10 must be between 0 and 9"+    (strD10Fail "58" :: Fallible D10) === fail "d10 must be a single character"++prop_strD10ListFail_examples :: Property+prop_strD10ListFail_examples = withTests 1 $ property $ do+    (strD10ListFail "5" :: Fallible [D10]) === return [D5]+    (strD10ListFail "a" :: Fallible [D10]) === fail "d10 must be between 0 and 9"+    (strD10ListFail "58" :: Fallible [D10]) === return [D5,D8]++prop_natD10Fail_examples :: Property+prop_natD10Fail_examples = withTests 1 $ property $ do+    (natD10Fail 5 :: Fallible D10) === return D5+    (natD10Fail 12 :: Fallible D10) === fail "d10 must be less than 10"++prop_integerD10Fail_examples :: Property+prop_integerD10Fail_examples = withTests 1 $ property $ do+    (integerD10Fail 5 :: Fallible D10) === return D5+    (integerD10Fail 12 :: Fallible D10) === fail "d10 must be between 0 and 9"+    (integerD10Fail (-5) :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_intD10Fail_examples :: Property+prop_intD10Fail_examples = withTests 1 $ property $ do+    (intD10Fail 5 :: Fallible D10) === return D5+    (intD10Fail 12 :: Fallible D10) === fail "d10 must be between 0 and 9"+    (intD10Fail (-5) :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_integralD10Fail_examples :: Property+prop_integralD10Fail_examples = withTests 1 $ property $ do+    (integralD10Fail (5 :: Integer) :: Fallible D10) === return D5+    (integralD10Fail (12 :: Integer) :: Fallible D10) === fail "d10 must be between 0 and 9"+    (integralD10Fail (-5 :: Integer) :: Fallible D10) === fail "d10 must be between 0 and 9"++prop_d10ListExp_examples :: Property+prop_d10ListExp_examples = withTests 1 $ property $ do+    $(d10ListExp "") === ([] :: [D10])+    $(d10ListExp "5") === [D5]+    $(d10ListExp "58") === [D5,D8]+    qFails (d10ListExp "a")++prop_d10ListPat_examples :: Property+prop_d10ListPat_examples = withTests 1 $ property $ do+    "B" === case id [D5, D6] of+        $(d10ListPat "42") -> "A"+        $(d10ListPat "56") -> "B"+        _                  -> "C"+    qFails (d10ListPat "a")++prop_qqExp_examples :: Property+prop_qqExp_examples = withTests 1 $ property $ do+    [d10list||] === ([] :: [D10])+    [d10list|5|] === [D5]+    [d10list|58|] === [D5,D8]++prop_qqPat_examples :: Property+prop_qqPat_examples = withTests 1 $ property $ do+    "B" === case id [D5, D6] of+        [d10list|41|] -> "A"+        [d10list|56|] -> "B"+        _             -> "C"++prop_arithmetic_examples :: Property+prop_arithmetic_examples = withTests 1 $ property $ do+    D2 + D3 === D5+    D6 + D7 === D3+    D7 - D5 === D2+    D3 - D7 === D6+    D2 * D4 === D8+    D7 * D8 === D6