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 +53/−0
- d10.cabal +112/−10
- license.txt +1/−1
- src/Data/D10/Char.hs +29/−35
- src/Data/D10/Num.hs +38/−40
- src/Data/D10/Predicate.hs +1/−9
- src/Data/D10/Safe.hs +27/−130
- test/AssertQFails.hs +15/−0
- test/Fallible.hs +10/−0
- test/char.hs +247/−0
- test/doctest.hs +0/−11
- test/num.hs +250/−0
- test/safe.hs +279/−0
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