ttc 1.2.1.0 → 1.3.0.0
raw patch · 4 files changed
+235/−23 lines, 4 filesdep ~basedep ~template-haskellPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, template-haskell
API changes (from Hackage documentation)
+ Data.TTC: instance (Control.Monad.Fail.MonadFail m, Language.Haskell.TH.Syntax.Quote m, Data.TTC.Parse a, Language.Haskell.TH.Syntax.Lift a) => Data.String.IsString (Language.Haskell.TH.Syntax.Code m a)
+ Data.TTC: parseOrFail :: (MonadFail m, Parse a, Textual t) => t -> m a
+ Data.TTC: parseOrFailBS :: (MonadFail m, Parse a) => ByteString -> m a
+ Data.TTC: parseOrFailBSB :: (MonadFail m, Parse a) => Builder -> m a
+ Data.TTC: parseOrFailBSL :: (MonadFail m, Parse a) => ByteString -> m a
+ Data.TTC: parseOrFailS :: (MonadFail m, Parse a) => String -> m a
+ Data.TTC: parseOrFailSBS :: (MonadFail m, Parse a) => ShortByteString -> m a
+ Data.TTC: parseOrFailT :: (MonadFail m, Parse a) => Text -> m a
+ Data.TTC: parseOrFailTL :: (MonadFail m, Parse a) => Text -> m a
+ Data.TTC: parseOrFailTLB :: (MonadFail m, Parse a) => Builder -> m a
Files
- CHANGELOG.md +13/−0
- src/Data/TTC.hs +146/−8
- test/Data/TTC/Test.hs +68/−0
- ttc.cabal +8/−15
CHANGELOG.md view
@@ -24,6 +24,19 @@ [KaC]: <https://keepachangelog.com/en/1.0.0/> +## 1.3.0.0 (2023-09-17)++### Breaking++* Add typed Template Haskell expression `IsString` orphan instance+* Add `parseOrFail` functions++### Non-Breaking++* Bump `bytestring` dependency version upper bound+* Bump `tasty` dependency version upper bound+* Bump `text` dependency version upper bound+ ## 1.2.1.0 (2023-03-21) ### Non-Breaking
src/Data/TTC.hs view
@@ -21,6 +21,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} #if __GLASGOW_HASKELL__ >= 900 {-# LANGUAGE ExplicitForAll #-}@@ -99,6 +100,17 @@ , parseMaybeBSL , parseMaybeBSB , parseMaybeSBS+ -- ** 'MonadFail' Parsing+ -- $ParseOrFail+ , parseOrFail+ , parseOrFailS+ , parseOrFailT+ , parseOrFailTL+ , parseOrFailTLB+ , parseOrFailBS+ , parseOrFailBSL+ , parseOrFailBSB+ , parseOrFailSBS -- ** Unsafe Parsing -- $ParseUnsafe , parseUnsafe@@ -152,8 +164,12 @@ ) where -- https://hackage.haskell.org/package/base+#if __GLASGOW_HASKELL__ <= 806+import Control.Monad.Fail (MonadFail)+#endif import Data.Int (Int16, Int32, Int64, Int8) import Data.Proxy (Proxy(Proxy), asProxyTypeOf)+import Data.String (IsString(fromString)) import Data.Word (Word16, Word32, Word64, Word8) import GHC.Stack (HasCallStack) import Text.Read (readMaybe)@@ -977,6 +993,78 @@ {-# INLINE parseMaybeSBS #-} ------------------------------------------------------------------------------+-- $ParseOrFail+--+-- The 'parseOrFail' function fails using 'MonadFail' on error instead of+-- using an 'Either' type. The rest of the functions are equivalent to+-- 'parseOrFail', but they specify the type being parsed from. Use them to+-- avoid having to write type annotations in cases where the type is+-- ambiguous.++-- | Parse or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFail :: (MonadFail m, Parse a, Textual t) => t -> m a+parseOrFail = either fail pure . parse+{-# INLINE parseOrFail #-}++-- | Parse from a 'String' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailS :: (MonadFail m, Parse a) => String -> m a+parseOrFailS = parseOrFail+{-# INLINE parseOrFailS #-}++-- | Parse from strict 'T.Text' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailT :: (MonadFail m, Parse a) => T.Text -> m a+parseOrFailT = parseOrFail+{-# INLINE parseOrFailT #-}++-- | Parse from lazy 'TL.Text' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailTL :: (MonadFail m, Parse a) => TL.Text -> m a+parseOrFailTL = parseOrFail+{-# INLINE parseOrFailTL #-}++-- | Parse from a @Text@ 'TLB.Builder' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailTLB :: (MonadFail m, Parse a) => TLB.Builder -> m a+parseOrFailTLB = parseOrFail+{-# INLINE parseOrFailTLB #-}++-- | Parse from a strict 'BS.ByteString' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailBS :: (MonadFail m, Parse a) => BS.ByteString -> m a+parseOrFailBS = parseOrFail+{-# INLINE parseOrFailBS #-}++-- | Parse from a lazy 'BSL.ByteString' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailBSL :: (MonadFail m, Parse a) => BSL.ByteString -> m a+parseOrFailBSL = parseOrFail+{-# INLINE parseOrFailBSL #-}++-- | Parse from a @ByteString@ 'BSB.Builder' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailBSB :: (MonadFail m, Parse a) => BSB.Builder -> m a+parseOrFailBSB = parseOrFail+{-# INLINE parseOrFailBSB #-}++-- | Parse from a 'SBS.ShortByteString' or fail using 'MonadFail'+--+-- @since 1.3.0.0+parseOrFailSBS :: (MonadFail m, Parse a) => SBS.ShortByteString -> m a+parseOrFailSBS = parseOrFail+{-# INLINE parseOrFailSBS #-}++------------------------------------------------------------------------------ -- $ParseUnsafe -- -- The 'parseUnsafe' function raises an exception on error instead of using an@@ -992,56 +1080,56 @@ parseUnsafe = either (error . ("parseUnsafe: " ++)) id . parse {-# INLINE parseUnsafe #-} --- | Unsafely parse to a 'String'+-- | Unsafely parse from a 'String' -- -- @since 0.1.0.0 parseUnsafeS :: (HasCallStack, Parse a) => String -> a parseUnsafeS = parseUnsafe {-# INLINE parseUnsafeS #-} --- | Unsafely parse to strict 'T.Text'+-- | Unsafely parse from strict 'T.Text' -- -- @since 0.1.0.0 parseUnsafeT :: (HasCallStack, Parse a) => T.Text -> a parseUnsafeT = parseUnsafe {-# INLINE parseUnsafeT #-} --- | Unsafely parse to lazy 'TL.Text'+-- | Unsafely parse from lazy 'TL.Text' -- -- @since 0.1.0.0 parseUnsafeTL :: (HasCallStack, Parse a) => TL.Text -> a parseUnsafeTL = parseUnsafe {-# INLINE parseUnsafeTL #-} --- | Unsafely parse to a @Text@ 'TLB.Builder'+-- | Unsafely parse from a @Text@ 'TLB.Builder' -- -- @since 1.1.0.0 parseUnsafeTLB :: (HasCallStack, Parse a) => TLB.Builder -> a parseUnsafeTLB = parseUnsafe {-# INLINE parseUnsafeTLB #-} --- | Unsafely parse to a strict 'BS.ByteString'+-- | Unsafely parse from a strict 'BS.ByteString' -- -- @since 0.1.0.0 parseUnsafeBS :: (HasCallStack, Parse a) => BS.ByteString -> a parseUnsafeBS = parseUnsafe {-# INLINE parseUnsafeBS #-} --- | Unsafely parse to a lazy 'BSL.ByteString'+-- | Unsafely parse from a lazy 'BSL.ByteString' -- -- @since 0.1.0.0 parseUnsafeBSL :: (HasCallStack, Parse a) => BSL.ByteString -> a parseUnsafeBSL = parseUnsafe {-# INLINE parseUnsafeBSL #-} --- | Unsafely parse to a @ByteString@ 'BSB.Builder'+-- | Unsafely parse from a @ByteString@ 'BSB.Builder' -- -- @since 1.1.0.0 parseUnsafeBSB :: (HasCallStack, Parse a) => BSB.Builder -> a parseUnsafeBSB = parseUnsafe {-# INLINE parseUnsafeBSB #-} --- | Unsafely parse to a 'SBS.ShortByteString'+-- | Unsafely parse from a 'SBS.ShortByteString' -- -- @since 1.1.0.0 parseUnsafeSBS :: (HasCallStack, Parse a) => SBS.ShortByteString -> a@@ -1478,6 +1566,56 @@ valid s = case parse s of Right x -> [|| x ||] Left err -> fail $ "Invalid constant: " ++ err+#endif++-- | This instance enables use of 'valid' without having to type @valid@. The+-- [OverloadedStrings](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/overloaded_strings.html)+-- extension must be enabled in the module where this functionality is used.+-- Note that this reduces the number of characters in the code, but it can+-- also make the code more difficult to understand by somebody who is not+-- already familiar with it. Typing @valid@ gives people a way to investigate+-- and understand what is going on.+--+-- Note that the typed Template Haskell API changed in GHC 9. The type+-- displayed in this documentation is determined by the version of GHC used to+-- build the documentation.+--+-- The type of this instance in GHC 9 or later is as follows:+--+-- @+-- (MonadFail m, THS.Quote m, Parse a, THS.Lift a) => IsString (THS.Code m a)+-- @+--+-- The type of this instance in previous versions of GHC is as follows:+--+-- @+-- (Parse a, THS.Lift a) => IsString (TH.Q (TH.TExp a))+-- @+--+-- This functionality can be used as follows in all supported versions of GHC.+-- The following is example usage from the @valid@ example:+--+-- @+-- sample2 :: Username+-- sample2 = $$("alice")+-- @+--+-- The parenthesis are not required from GHC 9. The following is example+-- usage from the @valid@ example:+--+-- @+-- sample2 :: Username+-- sample2 = $$"alice"+-- @+--+-- @since 1.3.0.0+#if __GLASGOW_HASKELL__ >= 900+instance (MonadFail m, THS.Quote m, Parse a, THS.Lift a)+ => IsString (THS.Code m a) where+ fromString = valid+#else+instance (Parse a, THS.Lift a) => IsString (TH.Q (TH.TExp a)) where+ fromString = valid #endif -- | Validate a constant at compile-time using a 'Parse' instance
test/Data/TTC/Test.hs view
@@ -971,6 +971,57 @@ testParseMaybeSBS = testCase "parseMaybeSBS" $ Just answer @=? TTC.parseMaybeSBS answerSBS +testParseOrFail :: TestTree+testParseOrFail = testGroup "parseOrFail"+ [ testCase "S" $ Just answer @=? TTC.parseOrFail answerS+ , testCase "T" $ Just answer @=? TTC.parseOrFail answerT+ , testCase "TL" $ Just answer @=? TTC.parseOrFail answerTL+ , testCase "TLB" $ Just answer @=? TTC.parseOrFail answerTLB+ , testCase "BS" $ Just answer @=? TTC.parseOrFail answerBS+ , testCase "BSL" $ Just answer @=? TTC.parseOrFail answerBSL+ , testCase "BSB" $ Just answer @=? TTC.parseOrFail answerBSB+ , testCase "SBS" $ Just answer @=? TTC.parseOrFail answerSBS+ -- successful 'parseOrFail' does not have any error type conversion:+ , testCase "noerror" $+ Just (PartialParser "test") @=? TTC.parseOrFail ("test" :: String)+ , testCase "negative" $+ Nothing @=? (TTC.parseOrFail ('-' : answerS) :: Maybe PosInt)+ , testCase "invalid" $+ Nothing @=? (TTC.parseOrFail ('a' : answerS) :: Maybe PosInt)+ ]++testParseOrFailS :: TestTree+testParseOrFailS = testCase "parseOrFailS" $+ Just answer @=? TTC.parseOrFailS answerS++testParseOrFailT :: TestTree+testParseOrFailT = testCase "parseOrFailT" $+ Just answer @=? TTC.parseOrFailT answerT++testParseOrFailTL :: TestTree+testParseOrFailTL = testCase "parseOrFailTL" $+ Just answer @=? TTC.parseOrFailTL answerTL++testParseOrFailTLB :: TestTree+testParseOrFailTLB = testCase "parseOrFailTLB" $+ Just answer @=? TTC.parseOrFailTLB answerTLB++testParseOrFailBS :: TestTree+testParseOrFailBS = testCase "parseOrFailBS" $+ Just answer @=? TTC.parseOrFailBS answerBS++testParseOrFailBSL :: TestTree+testParseOrFailBSL = testCase "parseOrFailBSL" $+ Just answer @=? TTC.parseOrFailBSL answerBSL++testParseOrFailBSB :: TestTree+testParseOrFailBSB = testCase "parseOrFailBSB" $+ Just answer @=? TTC.parseOrFailBSB answerBSB++testParseOrFailSBS :: TestTree+testParseOrFailSBS = testCase "parseOrFailSBS" $+ Just answer @=? TTC.parseOrFailSBS answerSBS+ testParseUnsafe :: TestTree testParseUnsafe = testGroup "parseUnsafe" [ testCase "S" $ answer @=? TTC.parseUnsafe answerS@@ -1183,6 +1234,13 @@ validConst :: TestString validConst = $$(TTC.valid "test") +testValidIsString :: TestTree+testValidIsString =+ testCase "validIsString" $ TestString "test" @=? validConst+ where+ validConst :: TestString+ validConst = $$("test")+ testValidOf :: TestTree testValidOf = testCase "validOf" $ TestString "test" @=? $$(TTC.validOf (Proxy :: Proxy TestString) "test")@@ -1268,6 +1326,15 @@ , testParseMaybeBSL , testParseMaybeBSB , testParseMaybeSBS+ , testParseOrFail+ , testParseOrFailS+ , testParseOrFailT+ , testParseOrFailTL+ , testParseOrFailTLB+ , testParseOrFailBS+ , testParseOrFailBSL+ , testParseOrFailBSB+ , testParseOrFailSBS , testParseUnsafe , testParseUnsafeS , testParseUnsafeT@@ -1289,6 +1356,7 @@ ] , testGroup "Valid" [ testValid+ , testValidIsString , testValidOf , testMkValid , testUntypedValidOf
ttc.cabal view
@@ -1,5 +1,5 @@ name: ttc-version: 1.2.1.0+version: 1.3.0.0 category: Data, Text synopsis: Textual Type Classes description:@@ -24,9 +24,9 @@ || ==8.8.4 || ==8.10.7 || ==9.0.2- || ==9.2.7- || ==9.4.4- || ==9.6.1+ || ==9.2.8+ || ==9.4.7+ || ==9.6.2 extra-source-files: CHANGELOG.md@@ -36,26 +36,19 @@ type: git location: https://github.com/ExtremaIS/ttc-haskell.git -flag write-hie- description: write .hie files- default: False- library hs-source-dirs: src exposed-modules: Data.TTC build-depends: base >=4.10.1 && <4.19- , bytestring >=0.10.8 && <0.12+ , bytestring >=0.10.8 && <0.13 , template-haskell >=2.12 && <2.21- , text >=1.2.2 && <2.1+ , text >=1.2.2 && <2.2 default-language: Haskell2010 default-extensions: OverloadedStrings- if flag(write-hie)- ghc-options: -Wall -fwrite-ide-info -hiedir=.hie- else- ghc-options: -Wall+ ghc-options: -Wall test-suite ttc-test type: exitcode-stdio-1.0@@ -67,7 +60,7 @@ build-depends: base , bytestring- , tasty >=0.11 && <1.5+ , tasty >=0.11 && <1.6 , tasty-hunit >=0.8 && <0.11 , template-haskell , text