d10 0.1.1.0 → 0.2.0.1
raw patch · 5 files changed
+379/−62 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.D10.Char: d10ListPat :: [D10] -> Q Pat
+ Data.D10.Char: d10Pat :: D10 -> Q Pat
+ Data.D10.Num: d10ListPat :: Integral a => [D10 a] -> Q Pat
+ Data.D10.Num: d10Pat :: Integral a => D10 a -> Q Pat
+ Data.D10.Safe: d10ListPat :: [D10] -> Q Pat
+ Data.D10.Safe: d10Pat :: D10 -> Q Pat
- Data.D10.Num: d10 :: forall a. (Lift a, Num a) => QuasiQuoter
+ Data.D10.Num: d10 :: forall a. (Lift a, Integral a) => QuasiQuoter
- Data.D10.Num: d10list :: forall a. (Lift a, Num a) => QuasiQuoter
+ Data.D10.Num: d10list :: forall a. (Lift a, Integral a) => QuasiQuoter
Files
- CHANGELOG.md +26/−0
- d10.cabal +2/−1
- src/Data/D10/Char.hs +108/−18
- src/Data/D10/Num.hs +110/−20
- src/Data/D10/Safe.hs +133/−23
+ CHANGELOG.md view
@@ -0,0 +1,26 @@+**v0.1.0.0**++ * Initial release++**v0.1.0.1**++ * Improve error messages when quasi-quoters are used in a+ non-expression context++**v0.1.1.0**++ * Add functions for generating Template Haskell expressions+ to be spliced, as alternatives to using the quasi-quoters++**v0.2.0.0**++ * Add Template Haskell splice patterns `d10Pat` and `d10ListPat`+ * Define `quotePat` for the quasi-quoters `d10` and `d10list`,+ so they can now be used with pattern matching+ * Add `Integral a` constraint to `d10` and `d10list` in the+ `Data.D10.Num` module, because this is needed for the+ definition of `quotePat`.++**v0.2.0.1**++ * Add `CHANGELOG.md` to package distribution
d10.cabal view
@@ -1,5 +1,5 @@ name: d10-version: 0.1.1.0+version: 0.2.0.1 category: Data synopsis: Digits 0-9 @@ -62,6 +62,7 @@ extra-source-files: README.md+ CHANGELOG.md source-repository head type: git
src/Data/D10/Char.hs view
@@ -1,9 +1,16 @@ {-# 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'@.+--+-- The following modules define @D10@ types in different ways+-- but are otherwise very similar to this one:+--+-- * "Data.D10.Num"+-- * "Data.D10.Safe" module Data.D10.Char (@@ -20,6 +27,10 @@ , d10Exp , d10ListExp + -- * Splice patterns+ , d10Pat+ , d10ListPat+ -- * Converting between D10 and Char , d10Char , charD10Maybe@@ -71,18 +82,17 @@ import Data.D10.Predicate -- base-import Control.Monad ((>=>))-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 Control.Monad ((>=>))+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) -- template-haskell-import Language.Haskell.TH (Exp, Q)-import Language.Haskell.TH.Quote (QuasiQuoter (..))-import Language.Haskell.TH.Syntax (Lift (lift))+import Language.Haskell.TH.Quote (QuasiQuoter (..))+import Language.Haskell.TH.Syntax (Exp (..), Lift (lift), Lit (..), Pat (..), Q) -- $setup -- >>> :set -XQuasiQuotes@@ -698,9 +708,7 @@ --------------------------------------------------- --- | A single base-10 digit.------ Produces an expression of type 'D10' that can be used+-- | Produces an expression of type 'D10' that can be used -- in a Template Haskell splice. -- -- >>> d10Nat $(d10Exp 5)@@ -710,13 +718,14 @@ -- ... -- ... 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 --- | A list of base-10 digits.------ Produces an expression of type @['D10']@ that can be used+-- | Produces an expression of type @['D10']@ that can be used -- in a Template Haskell splice. -- -- >>> d10Nat <$> $(d10ListExp "")@@ -732,12 +741,53 @@ -- ... -- ... d10 must be between 0 and 9 -- ...+--+-- You may also be interested in 'd10list', a quasi-quoter which+-- does something similar. d10ListExp :: String -> Q Exp d10ListExp = strD10ListFail >=> lift @[D10] --------------------------------------------------- +-- | Produces a pattern that can be used in a splice+-- to match a particular 'D10' value.+--+-- >>> :{+-- case (charD10Maybe '5') of+-- Just $(d10Pat [d10|4|]) -> "A"+-- Just $(d10Pat [d10|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))])++-- | 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"+-- >>> :}+-- "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)++--------------------------------------------------+ -- | A single base-10 digit. -- -- This quasi-quoter, when used as an expression, produces a@@ -755,11 +805,31 @@ -- ... -- ... 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+-- ... d10 :: QuasiQuoter d10 = QuasiQuoter { quoteExp = strD10Fail >=> lift- , quotePat = \_ -> fail "d10 cannot be used in a pattern context"+ , quotePat = strD10Fail >=> d10Pat , quoteType = \_ -> fail "d10 cannot be used in a type context" , quoteDec = \_ -> fail "d10 cannot be used in a declaration context" }@@ -782,11 +852,31 @@ -- ... -- ... d10 must be between 0 and 9 -- ...+--+-- This quasi-quoter can also be used as a pattern.+--+-- >>> :{+-- case [d10list|56|] of+-- [d10list|41|] -> "A"+-- [d10list|56|] -> "B"+-- _ -> "C"+-- >>> :}+-- "B"+--+-- >>> :{+-- case [d10list|56|] of+-- [d10list|4x|] -> "A"+-- [d10list|56|] -> "B"+-- _ -> "C"+-- >>> :}+-- ...+-- ... d10 must be between 0 and 9+-- ... d10list :: QuasiQuoter d10list = QuasiQuoter { quoteExp = strD10ListFail >=> lift- , quotePat = \_ -> fail "d10list cannot be used in a pattern context"+ , 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/Num.hs view
@@ -2,11 +2,18 @@ {-# 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@.+--+-- The following modules define @D10@ types in different ways+-- but are otherwise very similar to this one:+--+-- * "Data.D10.Char"+-- * "Data.D10.Safe" module Data.D10.Num (@@ -23,6 +30,10 @@ , d10Exp , d10ListExp + -- * Splice patterns+ , d10Pat+ , d10ListPat+ -- * Converting between D10 and Char , d10Char , charD10Maybe@@ -74,18 +85,17 @@ import Data.D10.Predicate -- base-import Control.Monad ((>=>))-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 Control.Monad ((>=>))+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) -- template-haskell-import Language.Haskell.TH (Exp, Q)-import Language.Haskell.TH.Quote (QuasiQuoter (..))-import Language.Haskell.TH.Syntax (Lift (lift))+import Language.Haskell.TH.Quote (QuasiQuoter (..))+import Language.Haskell.TH.Syntax (Exp (..), Lift (lift), Lit (..), Pat (..), Q) -- $setup -- >>> :set -XQuasiQuotes@@ -705,9 +715,7 @@ --------------------------------------------------- --- | A single base-10 digit.------ Produces an expression of type @'D10' a@ that can be used+-- | Produces an expression of type @'D10' a@ that can be used -- in a Template Haskell splice. -- -- >>> d10Nat $(d10Exp 5)@@ -717,13 +725,14 @@ -- ... -- ... d10 must be between 0 and 9 -- ...+--+-- 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) --- | A list of base-10 digits.------ Produces an expression of type @['D10' a]@ that can be used+-- | Produces an expression of type @['D10' a]@ that can be used -- in a Template Haskell splice. -- -- >>> d10Nat <$> $(d10ListExp "")@@ -739,12 +748,53 @@ -- ... -- ... d10 must be between 0 and 9 -- ...+--+-- 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] --------------------------------------------------- +-- | Produces a pattern that can be used in a splice+-- to match a particular @'D10' a@ value.+--+-- >>> :{+-- case (charD10Maybe '5') of+-- Just $(d10Pat [d10|4|]) -> "A"+-- Just $(d10Pat [d10|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))])++-- | 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"+-- >>> :}+-- "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)++---------------------------------------------------+ -- | A single base-10 digit. -- -- This quasi-quoter, when used as an expression, produces a@@ -762,11 +812,31 @@ -- ... -- ... 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+-- ... -d10 :: forall a. (Lift a, Num a) => QuasiQuoter+d10 :: forall a. (Lift a, Integral a) => QuasiQuoter d10 = QuasiQuoter { quoteExp = strD10Fail >=> lift @(D10 a)- , quotePat = \_ -> fail "d10 cannot be used in a pattern context"+ , quotePat = strD10Fail >=> d10Pat @a , quoteType = \_ -> fail "d10 cannot be used in a type context" , quoteDec = \_ -> fail "d10 cannot be used in a declaration context" }@@ -789,11 +859,31 @@ -- ... -- ... d10 must be between 0 and 9 -- ...+--+-- This quasi-quoter can also be used as a pattern.+--+-- >>> :{+-- case [d10list|56|] of+-- [d10list|41|] -> "A"+-- [d10list|56|] -> "B"+-- _ -> "C"+-- >>> :}+-- "B"+--+-- >>> :{+-- case [d10list|56|] of+-- [d10list|4x|] -> "A"+-- [d10list|56|] -> "B"+-- _ -> "C"+-- >>> :}+-- ...+-- ... d10 must be between 0 and 9+-- ... -d10list :: forall a. (Lift a, Num a) => QuasiQuoter+d10list :: forall a. (Lift a, Integral a) => QuasiQuoter d10list = QuasiQuoter { quoteExp = strD10ListFail >=> lift @[D10 a]- , quotePat = \_ -> fail "d10list cannot be used in a pattern context"+ , quotePat = strD10ListFail >=> d10ListPat @a , quoteType = \_ -> fail "d10list cannot be used in a type context" , quoteDec = \_ -> fail "d10list cannot be used in a declaration context" }
src/Data/D10/Safe.hs view
@@ -1,14 +1,20 @@ {-# LANGUAGE DeriveLift #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} -- | Defines a 'D10' type as -- @'D0' | 'D1' | 'D2' | 'D3' | 'D4' | 'D5' | 'D6' | 'D7' | 'D8' | 'D9'@. ----- This module is called "safe" because, in contrast with--- the alternative representations of a digit defined in--- "Data.D10.Char" and "Data.D10.Num", this 'D10' type does--- not include any possibility of representing an invalid--- non-digit value.+-- The following modules define @D10@ types in different ways+-- but are otherwise very similar to this one:+--+-- * "Data.D10.Char"+-- * "Data.D10.Num"+--+-- This module is called "safe" because, in contrast with the+-- alternative representations of a digit defined in the other+-- modules, this 'D10' type does not include any possibility+-- of representing an invalid non-digit value. module Data.D10.Safe (@@ -25,6 +31,10 @@ , d10Exp , d10ListExp + -- * Splice patterns+ , d10Pat+ , d10ListPat+ -- * Converting between D10 and Char , d10Char , charD10Maybe@@ -75,18 +85,17 @@ import Data.D10.Predicate -- base-import Control.Monad ((>=>))-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 Control.Monad ((>=>))+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) -- template-haskell-import Language.Haskell.TH (Exp, Q)-import Language.Haskell.TH.Quote (QuasiQuoter (..))-import Language.Haskell.TH.Syntax (Lift (lift))+import Language.Haskell.TH.Quote (QuasiQuoter (..))+import Language.Haskell.TH.Syntax (Exp (..), Lift (lift), Lit (..), Pat (..), Q) -- $setup -- >>> :set -XQuasiQuotes@@ -735,9 +744,7 @@ --------------------------------------------------- --- | A single base-10 digit.------ Produces an expression of type 'D10' that can be used+-- | Produces an expression of type 'D10' that can be used -- in a Template Haskell splice. -- -- >>> $(d10Exp 5)@@ -747,13 +754,14 @@ -- ... -- ... 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 --- | A list of base-10 digits.------ Produces an expression of type @['D10']@ that can be used+-- | Produces an expression of type @['D10']@ that can be used -- in a Template Haskell splice. -- -- >>> $(d10ListExp "")@@ -769,14 +777,76 @@ -- ... -- ... d10 must be between 0 and 9 -- ...+--+-- You may also be interested in 'd10list', a quasi-quoter which+-- does something similar. d10ListExp :: String -> Q Exp d10ListExp = strD10ListFail >=> lift @[D10] --------------------------------------------------- +-- | 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 |]++-- | 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"+-- >>> :}+-- "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'.++d10ListPat :: [D10] -> Q Pat+d10ListPat 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'. --@@ -792,11 +862,31 @@ -- ... -- ... 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+-- ... d10 :: QuasiQuoter d10 = QuasiQuoter { quoteExp = strD10Fail >=> lift- , quotePat = \_ -> fail "d10 cannot be used in a pattern context"+ , quotePat = strD10Fail >=> d10Pat , quoteType = \_ -> fail "d10 cannot be used in a type context" , quoteDec = \_ -> fail "d10 cannot be used in a declaration context" }@@ -819,11 +909,31 @@ -- ... -- ... d10 must be between 0 and 9 -- ...+--+-- This quasi-quoter can also be used as a pattern.+--+-- >>> :{+-- case [d10list|56|] of+-- [d10list|41|] -> "A"+-- [d10list|56|] -> "B"+-- _ -> "C"+-- >>> :}+-- "B"+--+-- >>> :{+-- case [d10list|56|] of+-- [d10list|4x|] -> "A"+-- [d10list|56|] -> "B"+-- _ -> "C"+-- >>> :}+-- ...+-- ... d10 must be between 0 and 9+-- ... d10list :: QuasiQuoter d10list = QuasiQuoter { quoteExp = strD10ListFail >=> lift- , quotePat = \_ -> fail "d10list cannot be used in a pattern context"+ , quotePat = strD10ListFail >=> d10ListPat , quoteType = \_ -> fail "d10list cannot be used in a type context" , quoteDec = \_ -> fail "d10list cannot be used in a declaration context" }