typed-encoding 0.4.2.0 → 0.5.0.0
raw patch · 55 files changed
+866/−1178 lines, 55 files
Files
- ChangeLog.md +43/−0
- README.md +3/−3
- src/Data/TypedEncoding.hs +10/−24
- src/Data/TypedEncoding/Combinators/Common.hs +3/−2
- src/Data/TypedEncoding/Combinators/Decode.hs +1/−1
- src/Data/TypedEncoding/Combinators/Encode.hs +1/−1
- src/Data/TypedEncoding/Combinators/Encode/Experimental.hs +1/−1
- src/Data/TypedEncoding/Combinators/Promotion.hs +4/−2
- src/Data/TypedEncoding/Combinators/Unsafe.hs +1/−1
- src/Data/TypedEncoding/Combinators/Validate.hs +6/−4
- src/Data/TypedEncoding/Common/Class.hs +2/−2
- src/Data/TypedEncoding/Common/Class/Common.hs +88/−0
- src/Data/TypedEncoding/Common/Class/Decode.hs +9/−0
- src/Data/TypedEncoding/Common/Class/Encode.hs +8/−0
- src/Data/TypedEncoding/Common/Class/IsStringR.hs +3/−0
- src/Data/TypedEncoding/Common/Class/Superset.hs +13/−11
- src/Data/TypedEncoding/Common/Class/Util.hs +0/−108
- src/Data/TypedEncoding/Common/Class/Validate.hs +4/−0
- src/Data/TypedEncoding/Common/Types/CheckedEnc.hs +24/−17
- src/Data/TypedEncoding/Common/Types/Common.hs +4/−5
- src/Data/TypedEncoding/Common/Types/Decoding.hs +37/−19
- src/Data/TypedEncoding/Common/Types/Enc.hs +6/−2
- src/Data/TypedEncoding/Common/Types/Exceptions.hs +3/−1
- src/Data/TypedEncoding/Common/Types/SomeAnnotation.hs +0/−41
- src/Data/TypedEncoding/Common/Types/SomeEnc.hs +0/−66
- src/Data/TypedEncoding/Common/Types/UncheckedEnc.hs +6/−2
- src/Data/TypedEncoding/Common/Types/Unsafe.hs +4/−2
- src/Data/TypedEncoding/Common/Types/Validation.hs +23/−8
- src/Data/TypedEncoding/Common/Util/TypeLits.hs +38/−13
- src/Data/TypedEncoding/Instances/Do/Sample.hs +0/−78
- src/Data/TypedEncoding/Instances/Enc/Base64.hs +3/−52
- src/Data/TypedEncoding/Instances/Enc/Warn/Base64.hs +72/−0
- src/Data/TypedEncoding/Instances/Restriction/Bool.hs +0/−434
- src/Data/TypedEncoding/Instances/Restriction/CHAR8.hs +3/−3
- src/Data/TypedEncoding/Instances/Restriction/D76.hs +7/−4
- src/Data/TypedEncoding/Instances/Restriction/Misc.hs +6/−9
- src/Data/TypedEncoding/Instances/Restriction/UTF8.hs +0/−2
- src/Data/TypedEncoding/Instances/Support.hs +0/−2
- src/Data/TypedEncoding/Instances/Support/Common.hs +0/−42
- src/Data/TypedEncoding/Instances/Support/Decode.hs +23/−4
- src/Data/TypedEncoding/Instances/Support/Helpers.hs +12/−22
- src/Data/TypedEncoding/Instances/Support/Unsafe.hs +1/−0
- src/Data/TypedEncoding/Instances/Support/Validate.hs +11/−22
- src/Data/TypedEncoding/Internal/Util.hs +5/−15
- src/Examples/TypedEncoding.hs +9/−3
- src/Examples/TypedEncoding/Conversions.hs +1/−1
- src/Examples/TypedEncoding/DiySignEncoding.hs +0/−130
- src/Examples/TypedEncoding/Instances/DiySignEncoding.hs +130/−0
- src/Examples/TypedEncoding/Instances/Do/Sample.hs +81/−0
- src/Examples/TypedEncoding/Overview.hs +7/−6
- src/Examples/TypedEncoding/SomeEnc.hs +76/−0
- src/Examples/TypedEncoding/SomeEnc/SomeAnnotation.hs +41/−0
- src/Examples/TypedEncoding/ToEncString.hs +4/−4
- src/Examples/TypedEncoding/Util.hs +20/−0
- typed-encoding.cabal +9/−9
ChangeLog.md view
@@ -8,6 +8,49 @@ - More module renaming to separate internal implementation code and code targeting examples - (post 0.5) "enc-B64" will be moved to a different package (more distant goal) +## 0.5.0++### Changes on a high level++- Most of the changes should not create a big impact on upgrading. Many definitions were moved to a different module but these modules are and had been re-exported by either `Data.TypedEncoding` or+`Data.TypedEncoding.Instances.Support`+- Some functionality has been moved to Examples or removed, notably:+ - "do-" encodings+ - `SomeEnc`, `SomeAnnotation`+ - `HasA` typeclass+- Some functions have been renamed or type signatures adjusted to follow consistent naming conventions. In most cases the changes have been made on previously deprecated definitions.+++### Details ++- Data.TypedEncoding.Instances.Do.Sample moved to Examples+- Examples.TypedEncoding folder re-org+- `Data.TypedEncoding.Instances.Support.Helpers` removed `foldEncStr`, `foldCheckedEncStr`+ renamed `splitSomePayload` to `splitCheckedPayload`+- `HasA` typeclass moved to Examples+- removed experimental `Data.TypedEncoding.Instances.Restriction.Bool` in favor of combinator helpers+ `Data.TypedEncoding.Instances.Support.Bool`+- `Data.TypedEncoding.Common.Types.SomeEnc` moved to Examples +- `Data.TypedEncoding.Common.Types.SomeAnnotation` moved to Examples+- camel-case of some property names+- Text instances for "Base64" moved to `Data.TypedEncoding.Instances.Enc.Warn.Base64`+- Removed instanced for `"r-()"` encoding+- Functions from `Data.TypedEncoding.Instances.Support.Common` moved to `Data.TypedEncoding.Instances.Support.Decode`+- Signature changed in previously deprecated function `runDecoding` to match `mn ~ alg` convention and deprecation removed+- Signature changed in previously deprecated function `runDecodings` to match `mns ~ algs` convention and deprecation removed+- Signature changed in previously deprecated function `runValidation` to match `mns ~ algs` convention and deprecation removed+- `runValidationChecks` renamed to `runValidationChecks'` to match /typed-encoding/ naming conventions. +- removed deprecated `propEncodesInto'`+- moved `Append` type family from from `Data.TypedEncoding.Common.Class.Util` to `Data.TypedEncoding.Common.Util.TypeLits`+- `Data.TypedEncoding.Common.Class.Util` renamed to `Data.TypedEncoding.Common.Class.Common`+- function `extractEither` removed from `Data.TypedEncoding.Internal.Util`+- function `withSomeSymbol` moved to `Data.TypedEncoding.Common.Util.TypeLits`+- function `proxyCons` moved to `Data.TypedEncoding.Common.Util.TypeLits`++- More general instances for some encodings in `Data.TypedEncoding.Instances.Restriction.Misc`+- `mkDecoding` deprecated in favor of `_mkDecoding` to follow the naming convention+- `mkValidation` deprecated in favor of `_mkValidation` to follow the naming convention+- `validR'` function renamed to `_validR` ## 0.4.2
README.md view
@@ -9,16 +9,16 @@ ```Haskell -- some data encoded in base 64-mydata :: Enc '["enc-B64"] ByteString+mydata :: Enc '["enc-B64"] c ByteString -- some text (utf8) data encoded in base 64 -myData :: Enc '["enc-B64", "r-UTF8"] ByteString+myData :: Enc '["enc-B64", "r-UTF8"] c ByteString ``` It allows to define precise string content annotations like: ```Haskell-ipaddr :: Enc '["r-IpV4"] Text+ipaddr :: Enc '["r-IpV4"] c Text ``` and provides ways for
src/Data/TypedEncoding.hs view
@@ -10,35 +10,36 @@ -- -- @ -- -- Base 64 encoded bytes (could represent binary files)--- Enc '["enc-B64"] ByteString+-- Enc '["enc-B64"] () ByteString -- -- -- Base 64 encoded UTF8 bytes--- Enc '["enc-B64", "r-UTF8"] ByteString+-- Enc '["enc-B64", "r-UTF8"] () ByteString -- -- -- Text that contains only ASCII characters--- Enc '["r-ASCII"] Text+-- Enc '["r-ASCII"] () Text -- @ -- -- or to do transformations to strings like -- -- @--- upper :: Text -> Enc '["do-UPPER"] Text+-- upper :: Text -> Enc '["do-UPPER"] c Text -- upper = ... -- @ -- -- or to define precise types to use with 'toEncString' and 'fromEncString' -- -- @--- date :: Enc '["r-date-%d/%b/%Y:%X %Z"] Text+-- date :: Enc '["r-date-%d/%b/%Y:%X %Z"] () Text -- date = toEncString ... -- @ ----- Primary focus of type-encodings is to provide type safe+-- Primary focus of /type-encodings/ is to provide type safe -- -- * /encoding/ -- * /decoding/ -- * /validation (recreation)/ (verification of existing payload) -- * type conversions between encoded types+-- * combinators for creating new encodings from existing encodings (e.g. by applying Boolean rules) -- -- of string-like data (@ByteString@, @Text@) that is subject of some -- encoding or formatting restrictions.@@ -62,7 +63,7 @@ -- -- Examples: @"r-UTF8"@, @"r-ASCII"@, upper alpha-numeric bound /r-ban/ restrictions like @"r-ban:999-999-9999"@ ----- == "do-" transformations+-- == "do-" transformations (not provided in this library other than as /Examples/ "Examples.TypedEncoding.Instances.Do.Sample") -- -- * /encoding/ applies transformation to the string (could be partial) -- * /decoding/ - typically none@@ -78,19 +79,7 @@ -- -- Examples: @"enc-B64"@ -- --- == "bool[Op]:" encodings ----- Encodings that are defined in terms of other encodings using boolean algebra.------ (early, beta version)------ Examples: ------ @"boolOr:(r-ban:999-999-9999)(r-ban:(999) 999-9999)"@ ------ "@boolNot:(r-ASCII)"------ -- = Call Site Usage -- -- To use this library import this module and one or more /instance/ or /combinator/ module.@@ -101,9 +90,7 @@ -- * "Data.TypedEncoding.Instances.Restriction.Misc" (replaces @Common@ from v0.2) -- * "Data.TypedEncoding.Instances.Restriction.ASCII" -- * "Data.TypedEncoding.Instances.Restriction.UTF8" --- * "Data.TypedEncoding.Instances.Restriction.Bool" (experimental / early alpha version, moved from @Combinators@ to @Instances@ in v0.3) -- * "Data.TypedEncoding.Instances.Restriction.BoundedAlphaNums" (moved from @Combinators@ to @Instances@ in v0.3)--- * "Data.TypedEncoding.Instances.Do.Sample" - This module is intended as example code and will be moved under 'Examples.TypedEncoding' in the future -- -- ... and needed conversions. --@@ -124,6 +111,7 @@ -- Examples of how to use this library are included in -- -- * "Examples.TypedEncoding" + module Data.TypedEncoding ( -- * @Enc@ and basic combinators@@ -132,8 +120,7 @@ , fromEncoding , getPayload - -- * Existentially quantified and untyped versions of @Enc@- , module Data.TypedEncoding.Common.Types.SomeEnc+ -- * Untyped versions of @Enc@ , module Data.TypedEncoding.Common.Types.CheckedEnc -- * @Encoding@ and basic combinators@@ -187,7 +174,6 @@ import Data.TypedEncoding.Common.Types.Common import Data.TypedEncoding.Common.Types.CheckedEnc-import Data.TypedEncoding.Common.Types.SomeEnc import Data.TypedEncoding.Common.Types.UncheckedEnc import Data.TypedEncoding.Common.Types.Exceptions import Data.TypedEncoding.Common.Class
src/Data/TypedEncoding/Combinators/Common.hs view
@@ -7,12 +7,13 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleContexts #-} --- | Combinators reexported in Data.TypedEncoding+-- | Common encoding combinators.+-- This module is re-exported in Data.TypedEncoding module Data.TypedEncoding.Combinators.Common where import Data.TypedEncoding.Common.Types import Data.TypedEncoding.Combinators.Unsafe-import Data.TypedEncoding.Common.Class.Util (Append)+import Data.TypedEncoding.Common.Util.TypeLits (Append) import GHC.TypeLits import Data.Proxy
src/Data/TypedEncoding/Combinators/Decode.hs view
@@ -18,7 +18,7 @@ import Data.TypedEncoding.Common.Types.Decoding import Data.TypedEncoding.Combinators.Common -import Data.TypedEncoding.Common.Class.Util+import Data.TypedEncoding.Common.Util.TypeLits import Data.TypedEncoding.Common.Class.Decode import Data.Functor.Identity import GHC.TypeLits
src/Data/TypedEncoding/Combinators/Encode.hs view
@@ -17,7 +17,7 @@ module Data.TypedEncoding.Combinators.Encode where import Data.TypedEncoding.Common.Types.Enc-import Data.TypedEncoding.Common.Class.Util -- Append+import Data.TypedEncoding.Common.Util.TypeLits -- Append import Data.TypedEncoding.Combinators.Common import Data.TypedEncoding.Common.Class.Encode import GHC.TypeLits
src/Data/TypedEncoding/Combinators/Encode/Experimental.hs view
@@ -16,7 +16,7 @@ import Data.TypedEncoding.Combinators.Encode import Data.TypedEncoding.Common.Types.Enc import Data.TypedEncoding.Common.Types.Common-import Data.TypedEncoding.Common.Class.Util -- Append+import Data.TypedEncoding.Common.Util.TypeLits -- Append import Data.TypedEncoding.Common.Class.Encode import Data.Functor.Identity import GHC.TypeLits
src/Data/TypedEncoding/Combinators/Promotion.hs view
@@ -12,7 +12,9 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE AllowAmbiguousTypes #-} --- | Promote and demote combinators.+-- | +-- Combinators allowing to add or remove redundant annotations.+-- Such operations are referred to in this package as promoting or demoting. module Data.TypedEncoding.Combinators.Promotion where import Data.TypedEncoding.Common.Class@@ -24,7 +26,7 @@ -- $setup -- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XTypeApplications--- >>> import Data.TypedEncoding.Common.Class.Util (displ)+-- >>> import Data.TypedEncoding.Common.Class.Common (displ) -- >>> import Data.TypedEncoding.Combinators.Unsafe (unsafeSetPayload) -- >>> import Data.TypedEncoding.Instances.Restriction.UTF8 () -- >>> import Data.TypedEncoding.Instances.Restriction.ASCII ()
src/Data/TypedEncoding/Combinators/Unsafe.hs view
@@ -10,7 +10,7 @@ -- | -- Currently this is the recommended way of recreating encoding from trusted input,--- if avoiding cost of "Data.TypedEncoding.Common.Types.Validation" is important.+-- if avoiding cost of "Data.TypedEncoding.Common.Types.Validation" is needed. -- -- @since 0.1.0.0 unsafeSetPayload :: conf -> str -> Enc enc conf str
src/Data/TypedEncoding/Combinators/Validate.hs view
@@ -7,9 +7,10 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE TypeApplications #-} --- | Combinators re-exported in Data.TypedEncoding.+-- | -- --- Decoding combinators that are backward compatible to v0.2 versions.+-- Validation combinators that are backward compatible to v0.2 versions.+-- This module is re-exported in Data.TypedEncoding. -- -- @since 0.3.0.0 module Data.TypedEncoding.Combinators.Validate where@@ -18,7 +19,8 @@ import Data.TypedEncoding.Combinators.Unsafe import Data.TypedEncoding.Common.Types import Data.TypedEncoding.Common.Class.Validate-import Data.TypedEncoding.Common.Class.Util (SymbolList, Append)+import Data.TypedEncoding.Common.Class.Common (SymbolList)+import Data.TypedEncoding.Common.Util.TypeLits (Append) import GHC.TypeLits import Data.Functor.Identity @@ -53,7 +55,7 @@ recreateWithValidations :: forall algs nms f c str . (Monad f) => Validations f nms algs c str -> Enc ('[]::[Symbol]) c str -> f (Enc nms c str) recreateWithValidations vers str@(UnsafeMkEnc _ _ pay) = let str0 :: Enc nms c str = withUnsafeCoerce id str- in withUnsafeCoerce (const pay) <$> runValidationChecks vers str0 + in withUnsafeCoerce (const pay) <$> runValidationChecks' vers str0 -- * v0.2 style recreate functions
src/Data/TypedEncoding/Common/Class.hs view
@@ -13,14 +13,14 @@ module Data.TypedEncoding.Common.Class ( module Data.TypedEncoding.Common.Class- , module Data.TypedEncoding.Common.Class.Util+ , module Data.TypedEncoding.Common.Class.Common , module Data.TypedEncoding.Common.Class.Encode , module Data.TypedEncoding.Common.Class.Decode , module Data.TypedEncoding.Common.Class.Validate , module Data.TypedEncoding.Common.Class.Superset ) where -import Data.TypedEncoding.Common.Class.Util+import Data.TypedEncoding.Common.Class.Common import Data.TypedEncoding.Common.Class.Encode import Data.TypedEncoding.Common.Class.Decode import Data.TypedEncoding.Common.Class.Validate
+ src/Data/TypedEncoding/Common/Class/Common.hs view
@@ -0,0 +1,88 @@++{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE AllowAmbiguousTypes #-}++-- | +-- This module defines @SymbolList@ and @Displ@ type classes+-- using by /typed-encoding/ used for display / testing as well as +-- for construction of untyped versions of @Enc@ (@CheckedEnc@ and @UncheckedEnc@)+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly.++module Data.TypedEncoding.Common.Class.Common where++import Data.TypedEncoding.Common.Types.Common++import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy.Char8 as BL+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL++import Data.Proxy+import qualified Data.List as L+import GHC.TypeLits++-- $setup+-- >>> :set -XScopedTypeVariables -XTypeApplications -XAllowAmbiguousTypes -XDataKinds++-- * Symbol List++-- |+-- @since 0.2.0.0+class SymbolList (xs::[Symbol]) where + symbolVals :: [String]++instance SymbolList '[] where+ symbolVals = []++-- |+-- >>> symbolVals @ '["FIRST", "SECOND"]+-- ["FIRST","SECOND"]+instance (SymbolList xs, KnownSymbol x) => SymbolList (x ': xs) where+ symbolVals = symbolVal (Proxy :: Proxy x) : symbolVals @xs+ +symbolVals_ :: forall xs . SymbolList xs => Proxy xs -> [String]+symbolVals_ _ = symbolVals @xs++-- * Display ++-- | Human friendly version of Show+--+-- @since 0.2.0.0+class Displ x where + displ :: x -> String+++instance Displ [EncAnn] where + displ x = "[" ++ L.intercalate "," x ++ "]"+instance Displ T.Text where+ displ x = "(Text " ++ T.unpack x ++ ")"+instance Displ TL.Text where+ displ x = "(TL.Text " ++ TL.unpack x ++ ")"+instance Displ B.ByteString where+ displ x = "(ByteString " ++ B.unpack x ++ ")" +instance Displ BL.ByteString where+ displ x = "(ByteString " ++ BL.unpack x ++ ")" +instance Displ String where+ displ x = "(String " ++ x ++ ")" ++++-- |+-- >>> displ (Proxy :: Proxy ["FIRST", "SECOND"])+-- "[FIRST,SECOND]"+instance (SymbolList xs) => Displ (Proxy xs) where+ displ _ = displ $ symbolVals @ xs+ -- "[" ++ (L.intercalate "," $ map displ $ symbolVals @ xs) ++ "]"+++
src/Data/TypedEncoding/Common/Class/Decode.hs view
@@ -8,6 +8,15 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE TypeApplications #-} ++-- |+-- Type classes accompanying decoding types defined in "Data.TypedEncoding.Common.Types.Decoding"+--+-- "Examples.TypedEncoding.Instances.DiySignEncoding" contains an implementation example.+--+-- "Examples.TypedEncoding.Overview" shows decoding usage examples.+-- +-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Class.Decode where import Data.TypedEncoding.Common.Types (UnexpectedDecodeEx(..))
src/Data/TypedEncoding/Common/Class/Encode.hs view
@@ -8,6 +8,14 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE TypeApplications #-} +-- | Type classes accompanying decoding types defined in "Data.TypedEncoding.Common.Types.Enc"+--+-- "Examples.TypedEncoding.Instances.DiySignEncoding" contains an implementation example.+--+-- "Examples.TypedEncoding.Overview" shows decoding usage examples.+-- +-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly.+ module Data.TypedEncoding.Common.Class.Encode where import Data.TypedEncoding.Common.Types.Enc
src/Data/TypedEncoding/Common/Class/IsStringR.hs view
@@ -7,6 +7,9 @@ -- | This Module will be removed in the future in favor of classes defined in -- "Data.TypedEncoding.Common.Class.Util.StringConstraints"+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly.+ module Data.TypedEncoding.Common.Class.IsStringR where import Data.Proxy
src/Data/TypedEncoding/Common/Class/Superset.hs view
@@ -13,6 +13,12 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ConstraintKinds #-} +-- |+-- This module contains typeclasses and type families that are used by /typed-encoding/ to +-- define subset / superset relationships between different encodings. +--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly.+ module Data.TypedEncoding.Common.Class.Superset where import Data.TypedEncoding.Common.Util.TypeLits@@ -143,13 +149,6 @@ _encodesInto :: forall y enc xs c str r . (IsSuperset y r ~ 'True, EncodingSuperset enc, r ~ EncSuperset enc) => Enc (enc ': xs) c str -> Enc (y ': enc ': xs) c str _encodesInto = injectInto . implEncInto --- |--- validates superset restriction--- --- Actual tests in the project /test/ suite.-propEncodesInto' :: forall algb algr b r str . (EncodingSuperset b, r ~ EncSuperset b, Eq str) => Encoding (Either EncodeEx) b algb () str -> Encoding (Either EncodeEx) r algr () str -> str -> Bool-propEncodesInto' = propEncodesIntoCheck-{-# DEPRECATED propEncodesInto' "Use propEncodesIntoCheck or propEncodesInto_" #-} propEncodesInto_ :: forall b r str algb algr. ( EncodingSuperset b@@ -166,7 +165,7 @@ -- | -- validates superset restriction -- --- Actual tests in the project /test/ suite.+-- Actual tests are in the project /test/ suite. propEncodesIntoCheck :: forall algb algr b r str . (Eq str) => Encoding (Either EncodeEx) b algb () str -> Encoding (Either EncodeEx) r algr () str -> str -> Bool propEncodesIntoCheck encb encr str = case runEncoding' @algb encb . toEncoding () $ str of@@ -190,9 +189,12 @@ -- | -- Aggregate version of 'EncodingSuperset' ----- This is not ideal but easy to implement.--- The issue is that this assumes restricted co-domain which is what often happens--- but often does not, e.g. it will not work well with id transformation.+-- It is used to assure type safety of conversion functions in "Data.TypedEncoding.Conv".+-- This approach is not ideal since+-- it produces an overly conservative restriction on encoding stack. +--+-- The issue is that this enforces restriction on the co-domain or each encoding and it does not take +-- into account the fact that the domain is already restricted, e.g. it will prevent adding id transformation to the stack. -- -- @since 0.4.0.0 class AllEncodeInto (superset :: Symbol) (encnms :: [Symbol]) where
− src/Data/TypedEncoding/Common/Class/Util.hs
@@ -1,108 +0,0 @@--{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE AllowAmbiguousTypes #-}---- | This module should be merged with --- "Data.TypedEncoding.Common.Util.TypeLits"------ Since both provide type level helpers-module Data.TypedEncoding.Common.Class.Util where--import Data.TypedEncoding.Common.Types.Common--import qualified Data.ByteString.Char8 as B-import qualified Data.ByteString.Lazy.Char8 as BL-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL--import Data.Proxy-import qualified Data.List as L-import GHC.TypeLits---- $setup--- >>> :set -XScopedTypeVariables -XTypeApplications -XAllowAmbiguousTypes -XDataKinds---- * Symbol List---- |--- @since 0.2.0.0-class SymbolList (xs::[Symbol]) where - symbolVals :: [String]--instance SymbolList '[] where- symbolVals = []---- |--- >>> symbolVals @ '["FIRST", "SECOND"]--- ["FIRST","SECOND"]-instance (SymbolList xs, KnownSymbol x) => SymbolList (x ': xs) where- symbolVals = symbolVal (Proxy :: Proxy x) : symbolVals @xs- -symbolVals_ :: forall xs . SymbolList xs => Proxy xs -> [String]-symbolVals_ _ = symbolVals @xs---- * Display ---- | Human friendly version of Show------ @since 0.2.0.0-class Displ x where - displ :: x -> String---instance Displ [EncAnn] where - displ x = "[" ++ L.intercalate "," x ++ "]"-instance Displ T.Text where- displ x = "(Text " ++ T.unpack x ++ ")"-instance Displ TL.Text where- displ x = "(TL.Text " ++ TL.unpack x ++ ")"-instance Displ B.ByteString where- displ x = "(ByteString " ++ B.unpack x ++ ")" -instance Displ BL.ByteString where- displ x = "(ByteString " ++ BL.unpack x ++ ")" -instance Displ String where- displ x = "(String " ++ x ++ ")" ------ |--- >>> displ (Proxy :: Proxy ["FIRST", "SECOND"])--- "[FIRST,SECOND]"-instance (SymbolList xs) => Displ (Proxy xs) where- displ _ = displ $ symbolVals @ xs- -- "[" ++ (L.intercalate "," $ map displ $ symbolVals @ xs) ++ "]"----- * Other---- TODO should this be imported from somewhere?---- |--- Type level list append--- --- @since 0.1.0.0-type family Append (xs :: [k]) (ys :: [k]) :: [k] where- Append '[] xs = xs- Append (y ': ys) xs = y ': Append ys xs---- | Polymorphic data payloads used to encode/decode------ This class is intended for example use only and will be moved to Example modules.--- --- Use your favorite polymorphic records / ad-hock product polymorphism library.------ @since 0.1.0.0-class HasA a c where- has :: c -> a--instance HasA () c where- has = const ()
src/Data/TypedEncoding/Common/Class/Validate.hs view
@@ -11,6 +11,10 @@ -- {-# LANGUAGE TypeApplications #-} {-# LANGUAGE AllowAmbiguousTypes #-} +-- |+-- Type classes accompanying decoding types defined in "Data.TypedEncoding.Common.Types.Validation"+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Class.Validate where import Data.TypedEncoding.Common.Types (RecreateEx(..))
src/Data/TypedEncoding/Common/Types/CheckedEnc.hs view
@@ -1,22 +1,30 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE ScopedTypeVariables #-}--- {-# LANGUAGE PolyKinds #-}--- {-# LANGUAGE DataKinds #-}--- {-# LANGUAGE TypeOperators #-}--- {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE StandaloneDeriving #-}+-- {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE RankNTypes #-} -- |--- Module defines 'CheckedEnc' - untyped ADT version of 'Enc' +-- Module defines 'CheckedEnc' - untyped ADT version of 'Enc'+--+-- A more dependently typed approach would be to define SomeEnc GADT+-- that accepts some @Enc '[..]@ in its constructor. The approach here+-- turns out to be isomorphic to @SomeEnc@ approach. Both, however, yield+-- somewhat different programming. +--+-- Post v0.4 /typed-encoding/ does not support @SomeEnc@ and it remains only as an /Example/.+-- +-- See "Examples.TypedEncoding.SomeEnc".+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. + module Data.TypedEncoding.Common.Types.CheckedEnc where import Data.TypedEncoding.Common.Types.Enc import Data.TypedEncoding.Common.Types.Common-import Data.TypedEncoding.Common.Class.Util+import Data.TypedEncoding.Common.Class.Common import Data.Proxy -- $setup@@ -27,8 +35,6 @@ -- * Untyped Enc --- constructor is to be treated as Unsafe to Encode and Decode instance implementations--- particular encoding instances may expose smart constructors for limited data types -- | Represents some validated encoded string. --@@ -39,7 +45,8 @@ -- @since 0.2.0.0 data CheckedEnc conf str = UnsafeMkCheckedEnc [EncAnn] conf str -- ^ @since 0.3.0.0 -- Constructor renamed from previous versions-+ -- This constructor is considered unsafe as pattern matching on it and+ -- using it allows access to the encoded payload. deriving (Show, Eq) -- |@@ -76,19 +83,19 @@ -- | -- >>> let encsometest = UnsafeMkCheckedEnc ["TEST"] () $ T.pack "hello"--- >>> proc_toCheckedEncFromCheckedEnc @'["TEST"] encsometest+-- >>> procToCheckedEncFromCheckedEnc @'["TEST"] encsometest -- True--- >>> proc_toCheckedEncFromCheckedEnc @'["TEST1"] encsometest+-- >>> procToCheckedEncFromCheckedEnc @'["TEST1"] encsometest -- False-proc_toCheckedEncFromCheckedEnc :: forall xs c str . (SymbolList xs, Eq c, Eq str) => CheckedEnc c str -> Bool-proc_toCheckedEncFromCheckedEnc x = (== Just x) . fmap (toCheckedEnc @ xs) . fromCheckedEnc $ x+procToCheckedEncFromCheckedEnc :: forall xs c str . (SymbolList xs, Eq c, Eq str) => CheckedEnc c str -> Bool+procToCheckedEncFromCheckedEnc x = (== Just x) . fmap (toCheckedEnc @ xs) . fromCheckedEnc $ x -- | -- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text--- >>> proc_fromCheckedEncToCheckedEnc enctest+-- >>> procFromCheckedEncToCheckedEnc enctest -- True-proc_fromCheckedEncToCheckedEnc :: forall xs c str . (SymbolList xs, Eq c, Eq str) => Enc xs c str -> Bool-proc_fromCheckedEncToCheckedEnc x = (== Just x) . fromCheckedEnc . toCheckedEnc $ x+procFromCheckedEncToCheckedEnc :: forall xs c str . (SymbolList xs, Eq c, Eq str) => Enc xs c str -> Bool+procFromCheckedEncToCheckedEnc x = (== Just x) . fromCheckedEnc . toCheckedEnc $ x -- | -- >>> displ $ unsafeCheckedEnc ["TEST"] () ("hello" :: T.Text)
src/Data/TypedEncoding/Common/Types/Common.hs view
@@ -2,15 +2,14 @@ {-# LANGUAGE PolyKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeOperators #-}--- {-# LANGUAGE FlexibleInstances #-}--- {-# LANGUAGE FlexibleContexts #-}--- {-# LANGUAGE UndecidableInstances #-}--- {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ConstraintKinds #-} +-- | Common types and some type families used in /typed-encoding/ definitions.+-- +-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Types.Common where import Data.TypedEncoding.Common.Util.TypeLits@@ -49,7 +48,7 @@ -- | -- Converts encoding name to algorithm name, this assumes the ":" delimiter expected by this library. ----- This allows working with open encoding definitions such as "r-ban" or "r-bool"+-- This allows working with open encoding definitions such as "r-ban" -- -- >>> :kind! AlgNm "enc-B64" -- ...
src/Data/TypedEncoding/Common/Types/Decoding.hs view
@@ -12,9 +12,9 @@ {-# OPTIONS_GHC -Wno-partial-type-signatures #-} -- |--- Internal definition of types--- -- Decoding types for @Enc@+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Types.Decoding where import Data.Proxy@@ -26,15 +26,21 @@ -- | -- Similar to 'Data.TypedEncoding.Common.Types.Enc.Encoding' ----- Used to create instances of decoding.+-- Wraps the decoding function. --+-- Can be used with 'Data.TypedEncoding.Common.Class.Decode.Decode' type class.+-- +-- "Examples.TypedEncoding.Instances.DiySignEncoding" contains an implementation example.+--+-- "Examples.TypedEncoding.Overview" shows decoding usage examples.+-- -- @since 0.3.0.0 data Decoding f (nm :: Symbol) (alg :: Symbol) conf str where -- | Consider this constructor as private or use it with care --- -- Using this constructor:+ -- Using that constructor: -- @- -- MkDecoding :: Proxy nm -> (forall (xs :: [Symbol]) . Enc (nm ': xs) conf str -> f (Enc xs conf str)) -> Decoding f nm (AlgNm nm) conf str+ -- UnsafeMkDecoding :: Proxy nm -> (forall (xs :: [Symbol]) . Enc (nm ': xs) conf str -> f (Enc xs conf str)) -> Decoding f nm (AlgNm nm) conf str -- @ -- -- would make compilation much slower@@ -45,15 +51,27 @@ -- -- @since 0.3.0.0 mkDecoding :: forall f (nm :: Symbol) conf str . (forall (xs :: [Symbol]) . Enc (nm ': xs) conf str -> f (Enc xs conf str)) -> Decoding f nm (AlgNm nm) conf str-mkDecoding = UnsafeMkDecoding Proxy+mkDecoding = _mkDecoding +{-# DEPRECATED mkDecoding "Use _mkDecoding" #-}++++-- | Type safe smart constructor+-- (See also 'Data.TypedEncoding.Common.Types.Enc._mkEncoding') +-- +-- This function follows the naming convention of using "_" when the typechecker figures out @alg@+-- @since 0.5.0.0 +_mkDecoding :: forall f (nm :: Symbol) conf str . (forall (xs :: [Symbol]) . Enc (nm ': xs) conf str -> f (Enc xs conf str)) -> Decoding f nm (AlgNm nm) conf str+_mkDecoding = UnsafeMkDecoding Proxy+ -- |--- @since 0.3.0.0-runDecoding :: forall alg nm f xs conf str . Decoding f nm alg conf str -> Enc (nm ': xs) conf str -> f (Enc xs conf str)+-- This function assumes @mn ~ alg@, making its type different from previous (before v.0.5) versions.+--+-- @since 0.5.0.0+runDecoding :: forall nm f xs conf str . Decoding f nm nm conf str -> Enc (nm ': xs) conf str -> f (Enc xs conf str) runDecoding (UnsafeMkDecoding _ fn) = fn -{-# DEPRECATED runDecoding "Use runDecoding'" #-}- -- | -- @since 0.3.0.0 runDecoding' :: forall alg nm f xs conf str . Decoding f nm alg conf str -> Enc (nm ': xs) conf str -> f (Enc xs conf str)@@ -65,7 +83,7 @@ -- -- @since 0.3.0.0 _runDecoding :: forall nm f xs conf str alg . (AlgNm nm ~ alg) => Decoding f nm alg conf str -> Enc (nm ': xs) conf str -> f (Enc xs conf str)-_runDecoding = runDecoding @(AlgNm nm)+_runDecoding = runDecoding' @(AlgNm nm) -- | -- Wraps a list of @Decoding@ elements.@@ -81,21 +99,21 @@ ConsD :: Decoding f nm alg conf str -> Decodings f nms algs conf str -> Decodings f (nm ': nms) (alg ': algs) conf str -- |--- @since 0.3.0.0-runDecodings :: forall algs nms f c str . (Monad f) => Decodings f nms algs c str -> Enc nms c str -> f (Enc ('[]::[Symbol]) c str)-runDecodings = runDecodings' @algs @nms--{-# DEPRECATED runDecodings "Use runDecodings'" #-}+-- This function assumes @nms ~ algs@, making its type different from previous (before v.0.5) versions.+--+-- @since 0.5.0.0+runDecodings :: forall nms f c str . (Monad f) => Decodings f nms nms c str -> Enc nms c str -> f (Enc ('[]::[Symbol]) c str)+runDecodings = runDecodings' @nms @nms runDecodings' :: forall algs nms f c str . (Monad f) => Decodings f nms algs c str -> Enc nms c str -> f (Enc ('[]::[Symbol]) c str) runDecodings' ZeroD enc0 = pure enc0 runDecodings' (ConsD fn xs) enc = - let re :: f (Enc _ c str) = runDecoding fn enc- in re >>= runDecodings xs+ let re :: f (Enc _ c str) = runDecoding' fn enc+ in re >>= runDecodings' xs -- | At possibly big compilation cost, have compiler figure out algorithm names. -- -- @since 0.3.0.0 _runDecodings :: forall nms f c str algs . (Monad f, algs ~ AlgNmMap nms) => Decodings f nms algs c str -> Enc nms c str -> f (Enc ('[]::[Symbol]) c str)-_runDecodings = runDecodings @(AlgNmMap nms)+_runDecodings = runDecodings' @(AlgNmMap nms)
src/Data/TypedEncoding/Common/Types/Enc.hs view
@@ -11,14 +11,18 @@ {-# LANGUAGE PartialTypeSignatures #-} {-# OPTIONS_GHC -Wno-partial-type-signatures #-} -- |--- Internal definition of types+-- Contains main @Enc@ type that carries encoded payload as well as+-- @Encoding@ and @Encodings@ types contains encoding functions.+-- This module also contains basic combinators for these types.+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Types.Enc where import Data.Proxy import GHC.TypeLits -import Data.TypedEncoding.Common.Class.Util+import Data.TypedEncoding.Common.Class.Common import Data.TypedEncoding.Common.Types.Common -- $setup
src/Data/TypedEncoding/Common/Types/Exceptions.hs view
@@ -9,7 +9,9 @@ -- {-# LANGUAGE RankNTypes #-} -- |--- Internal definition of types+-- Exception types used in /typed-encoding/+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Types.Exceptions where
− src/Data/TypedEncoding/Common/Types/SomeAnnotation.hs
@@ -1,41 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE RankNTypes #-}---- | internally used existential type for taking track of annotations-module Data.TypedEncoding.Common.Types.SomeAnnotation where--import Data.TypedEncoding.Common.Types.Common-import Data.TypedEncoding.Common.Class.Util-import Data.TypedEncoding.Internal.Util-import Data.Proxy-import GHC.TypeLits---- |--- @since 0.2.0.0-data SomeAnnotation where- MkSomeAnnotation :: SymbolList xs => Proxy xs -> SomeAnnotation---- |--- @since 0.2.0.0-withSomeAnnotation :: SomeAnnotation -> (forall xs . SymbolList xs => Proxy xs -> r) -> r-withSomeAnnotation (MkSomeAnnotation p) fn = fn p----- | folds over SomeSymbol list using withSomeSymbol and proxyCons--- @since 0.2.0.0-someAnnValue :: [EncAnn] -> SomeAnnotation-someAnnValue xs = - foldr (fn . someSymbolVal) (MkSomeAnnotation (Proxy :: Proxy '[])) xs- where - somesymbs = map someSymbolVal xs- fn ss (MkSomeAnnotation pxs) = withSomeSymbol ss (\px -> MkSomeAnnotation (px `proxyCons` pxs)) ---- |--- @since 0.2.0.0-proxyCons :: forall (x :: Symbol) (xs :: [Symbol]) . Proxy x -> Proxy xs -> Proxy (x ': xs)-proxyCons _ _ = Proxy
− src/Data/TypedEncoding/Common/Types/SomeEnc.hs
@@ -1,66 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE RankNTypes #-}---- |--- Module defines 'SomeEnc' - existentially quantified version of @Enc@--- and basic combinators--module Data.TypedEncoding.Common.Types.SomeEnc where--import Data.TypedEncoding.Common.Types.Enc-import Data.TypedEncoding.Common.Class.Util-import Data.TypedEncoding.Common.Types.SomeAnnotation-import Data.TypedEncoding.Common.Types.CheckedEnc---- $setup--- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes--- >>> import qualified Data.Text as T--- >>> import Data.TypedEncoding.Combinators.Unsafe------ | Existentially quantified quantified @Enc@--- effectively isomorphic to 'CheckedEnc'------ @since 0.2.0.0-data SomeEnc conf str where- MkSomeEnc :: SymbolList xs => Enc xs conf str -> SomeEnc conf str---- |--- @since 0.2.0.0 -withSomeEnc :: SomeEnc conf str -> (forall xs . SymbolList xs => Enc xs conf str -> r) -> r-withSomeEnc (MkSomeEnc enc) f = f enc---- |--- @since 0.2.0.0 -toSome :: SymbolList xs => Enc xs conf str -> SomeEnc conf str-toSome = MkSomeEnc---- | --- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text--- >>> someToChecked . MkSomeEnc $ enctest--- UnsafeMkCheckedEnc ["TEST"] () "hello"--- --- @since 0.2.0.0 -someToChecked :: SomeEnc conf str -> CheckedEnc conf str-someToChecked se = withSomeEnc se toCheckedEnc---- | --- >>> let tst = unsafeCheckedEnc ["TEST"] () "test"--- >>> displ $ checkedToSome tst--- "Some (Enc '[TEST] () (String test))"--- --- @since 0.2.0.0 s-checkedToSome :: CheckedEnc conf str -> SomeEnc conf str-checkedToSome (UnsafeMkCheckedEnc xs c s) = withSomeAnnotation (someAnnValue xs) (\p -> MkSomeEnc (UnsafeMkEnc p c s))----- |--- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text--- >>> displ $ MkSomeEnc enctest--- "Some (Enc '[TEST] () (Text hello))"-instance (Show c, Displ str) => Displ (SomeEnc c str) where- displ (MkSomeEnc en) = - "Some (" ++ displ en ++ ")"
src/Data/TypedEncoding/Common/Types/UncheckedEnc.hs view
@@ -9,12 +9,14 @@ {-# LANGUAGE AllowAmbiguousTypes #-} -- |--- Internal definition of types+-- Defines @UncheckedEnc@ representing not verified encoding and basic combinators for using it. +--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Types.UncheckedEnc where import Data.Proxy-import Data.TypedEncoding.Common.Class.Util+import Data.TypedEncoding.Common.Class.Common import Data.TypedEncoding.Common.Types.Common -- $setup@@ -25,6 +27,8 @@ -- * UncheckedEnc for validation, similar to CheckedEnc but not verified -- | Represents some encoded string where encoding was not validated.+--+-- Encoding is not tracked at the type level. -- -- Similar to 'Data.TypedEncoding.Common.Types.CheckedEnc' but unlike -- @CheckedEnc@ it can contain payloads that have invalid encoding.
src/Data/TypedEncoding/Common/Types/Unsafe.hs view
@@ -12,8 +12,10 @@ import Data.TypedEncoding.Common.Types --- | Allows to operate within Enc. These are considered unsafe.--- keeping the same list of encodings +-- | Allows to operate within @Enc@+-- keeping the same list of encodings.+--+-- These are considered unsafe. -- -- @since 0.1.0.0 newtype Unsafe enc conf str = Unsafe {runUnsafe :: Enc enc conf str} deriving (Show)
src/Data/TypedEncoding/Common/Types/Validation.hs view
@@ -22,6 +22,8 @@ -- -- Use of 'Data.TypedEncoding.Combinators.Unsafe.unsafeSetPayload' currently recommended -- for recovering 'Enc' from trusted input sources (if avoiding cost of Validation is important).+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly. module Data.TypedEncoding.Common.Types.Validation where @@ -50,12 +52,21 @@ -- @since 0.3.0.0 mkValidation :: forall f (nm :: Symbol) conf str . (forall (xs :: [Symbol]) . Enc (nm ': xs) conf str -> f (Enc xs conf str)) -> Validation f nm (AlgNm nm) conf str mkValidation = UnsafeMkValidation Proxy+{-# DEPRECATED mkValidation "Use _mkValidation" #-} -runValidation :: forall alg nm f xs conf str . Validation f nm alg conf str -> Enc (nm ': xs) conf str -> f (Enc xs conf str)-runValidation (UnsafeMkValidation _ fn) = fn+-- | Type safe smart constructor+-- adding the type family @(AlgNm nm)@ restriction to UnsafeMkValidation slows down compilation, especially in tests. +--+-- This function follows the naming convention of using "_" when the typechecker figures out @alg@+--+-- @since 0.5.0.0+_mkValidation :: forall f (nm :: Symbol) conf str . (forall (xs :: [Symbol]) . Enc (nm ': xs) conf str -> f (Enc xs conf str)) -> Validation f nm (AlgNm nm) conf str+_mkValidation = UnsafeMkValidation Proxy -{-# DEPRECATED runValidation "Use runValidation''" #-} +runValidation :: forall nm f xs conf str . Validation f nm nm conf str -> Enc (nm ': xs) conf str -> f (Enc xs conf str)+runValidation (UnsafeMkValidation _ fn) = fn+ runValidation' :: forall alg nm f xs conf str . Validation f nm alg conf str -> Enc (nm ': xs) conf str -> f (Enc xs conf str) runValidation' (UnsafeMkValidation _ fn) = fn @@ -80,15 +91,19 @@ ZeroV :: Validations f '[] '[] conf str ConsV :: Validation f nm alg conf str -> Validations f nms algs conf str -> Validations f (nm ': nms) (alg ': algs) conf str ++ -- | This basically puts payload in decoded state. -- More useful combinators are in "Data.TypedEncoding.Combinators.Validate" ----- @since 0.3.0.0-runValidationChecks :: forall algs nms f c str . (Monad f) => Validations f nms algs c str -> Enc nms c str -> f (Enc ('[]::[Symbol]) c str)-runValidationChecks ZeroV enc0 = pure enc0-runValidationChecks (ConsV fn xs) enc = +-- (@runValidationChecks@ before v0.5)+--+-- @since 0.5.0.0+runValidationChecks' :: forall algs nms f c str . (Monad f) => Validations f nms algs c str -> Enc nms c str -> f (Enc ('[]::[Symbol]) c str)+runValidationChecks' ZeroV enc0 = pure enc0+runValidationChecks' (ConsV fn xs) enc = let re :: f (Enc _ c str) = runValidation' fn enc- in re >>= runValidationChecks xs+ in re >>= runValidationChecks' xs -- -- | At possibly big compilation cost, have compiler figure out algorithm names.
src/Data/TypedEncoding/Common/Util/TypeLits.hs view
@@ -11,6 +11,8 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE RankNTypes #-}+-- {-# LANGUAGE GADTs #-} -- | TypeLits related utilities.@@ -19,59 +21,82 @@ -- -- Uses @symbols@ library for its ToList type family. ----- Currently this is spread out in different modules------ * "Data.TypedEncoding.Common.Class.Util"--- * "Data.TypedEncoding.Common.Types.SomeAnnotation"------ (TODO) these will need to get consolidated. module Data.TypedEncoding.Common.Util.TypeLits where import GHC.TypeLits import Data.Symbol.Ascii+import Data.Proxy -- $setup -- >>> :set -XScopedTypeVariables -XTypeFamilies -XKindSignatures -XDataKinds --- !+-- |+-- Convenience combinator missing in TypeLits, See "Examples.TypedEncoding.SomeEnc.SomeAnnotation"+-- "Examples.TypedEncoding.SomeEnc.someAnnValue"+--+-- @since 0.2.0.0+withSomeSymbol :: SomeSymbol -> (forall x. KnownSymbol x => Proxy x -> r) -> r+withSomeSymbol s fn = case s of + SomeSymbol p -> fn p+++-- |+-- (Moved from previously defined module @Data.TypedEncoding.Common.Types.SomeAnnotation@)+-- +-- @since 0.2.0.0+proxyCons :: forall (x :: Symbol) (xs :: [Symbol]) . Proxy x -> Proxy xs -> Proxy (x ': xs)+proxyCons _ _ = Proxy++-- |+-- Type level list append+--+-- (moved from @Data.TypedEncoding.Common.Class.Common@)+--+-- @since 0.1.0.0+type family Append (xs :: [k]) (ys :: [k]) :: [k] where+ Append '[] xs = xs+ Append (y ': ys) xs = y ': Append ys xs+++-- | -- @since 0.2.1.0 type family AcceptEq (msg :: ErrorMessage) (c :: Ordering) :: Bool where AcceptEq _ EQ = True AcceptEq msg _ = TypeError msg --- !+-- | -- @since 0.4.0.0 type family OrdBool (c :: Ordering) :: Bool where OrdBool EQ = 'True OrdBool _ = 'False --- !+-- | -- @since 0.2.1.0 type family And (b1 :: Bool) (b2 :: Bool) :: Bool where And 'True 'True = 'True And _ _ = 'False --- !+-- | -- @since 0.2.1.0 type family Or (b1 :: Bool) (b2 :: Bool) :: Bool where Or 'False 'False = 'False Or _ _ = 'True --- !+-- | -- @since 0.2.1.0 type family If (b1 :: Bool) (a :: k) (b :: k) :: k where If 'True a _ = a If 'False _ b = b --- !+-- | -- @since 0.2.1.0 type family Repeat (n :: Nat) (s :: Symbol) :: Symbol where Repeat 0 s = "" Repeat n s = AppendSymbol s (Repeat (n - 1) s) --- !+-- | -- @since 0.2.1.0 type family Fst (s :: (k,h)) :: k where Fst ('(,) a _) = a
− src/Data/TypedEncoding/Instances/Do/Sample.hs
@@ -1,78 +0,0 @@--{-# LANGUAGE DataKinds #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}---- | This module defines some sample "do-" encodings--- currently for example use only.------ WARNING this Module will be moved to Examples in future versions-module Data.TypedEncoding.Instances.Do.Sample where--import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.ByteString as B--import Data.Char--import Data.TypedEncoding.Instances.Support-import Data.TypedEncoding.Instances.Support.Unsafe---- |--- @since 0.3.0.0 -instance Applicative f => Encode f "do-UPPER" "do-UPPER" c T.Text where- encoding = _implEncodingP T.toUpper--instance (RecreateErr f, Applicative f) => Validate f "do-UPPER" "do-UPPER" c T.Text where- validation = mkValidation $- implTranF (asRecreateErr @"do-UPPER" . (\t -> - let (g,b) = T.partition isUpper t- in if T.null b- then Right t- else Left $ "Found not upper case chars " ++ T.unpack b)- )--instance Applicative f => Encode f "do-UPPER" "do-UPPER" c TL.Text where- encoding = _implEncodingP TL.toUpper----- |--- @since 0.3.0.0 -instance Applicative f => Encode f "do-lower" "do-lower" c T.Text where- encoding = _implEncodingP T.toLower --instance Applicative f => Encode f "do-lower" "do-lower" c TL.Text where- encoding = _implEncodingP TL.toLower ---- |--- @since 0.3.0.0 -instance Applicative f => Encode f "do-Title" "do-Title" c T.Text where- encoding = _implEncodingP T.toTitle --instance Applicative f => Encode f "do-Title" "do-Title" c TL.Text where- encoding = _implEncodingP TL.toTitle ---- |--- @since 0.3.0.0 -instance Applicative f => Encode f "do-reverse" "do-reverse" c T.Text where- encoding = _implEncodingP T.reverse -instance Applicative f => Encode f "do-reverse" "do-reverse" c TL.Text where- encoding = _implEncodingP TL.reverse ---- |--- @since 0.1.0.0-newtype SizeLimit = SizeLimit {unSizeLimit :: Int} deriving (Eq, Show)---- |--- @since 0.3.0.0 -instance (HasA SizeLimit c, Applicative f) => Encode f "do-size-limit" "do-size-limit" c T.Text where- encoding = _implEncodingConfP (T.take . unSizeLimit . has @ SizeLimit) -instance (HasA SizeLimit c, Applicative f) => Encode f "do-size-limit" "do-size-limit" c B.ByteString where- encoding = _implEncodingConfP (B.take . unSizeLimit . has @ SizeLimit) -
src/Data/TypedEncoding/Instances/Enc/Base64.hs view
@@ -17,11 +17,8 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Encoding as TE -import qualified Data.Text.Lazy.Encoding as TEL + import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Base64.Lazy as BL64 @@ -30,7 +27,6 @@ -- $setup -- >>> :set -XOverloadedStrings -XScopedTypeVariables -XKindSignatures -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XPartialTypeSignatures -XFlexibleInstances -XTypeApplications -- >>> import Test.QuickCheck--- >>> import Test.QuickCheck.Instances.Text() -- >>> import Test.QuickCheck.Instances.ByteString() -- >>> :{ -- instance Arbitrary (UncheckedEnc () B.ByteString) where @@ -116,16 +112,7 @@ encB64BL = _implEncodingP BL64.encode --- | This instance will likely be removed in future versions (performance concerns)------ @since 0.3.0.0-instance Applicative f => Encode f "enc-B64" "enc-B64" c T.Text where- encoding = endB64T --- | This function will likely be removed in future versions (performance concerns)-endB64T :: Applicative f => Encoding f "enc-B64" "enc-B64" c T.Text-endB64T = _implEncodingP (TE.decodeUtf8 . B64.encode . TE.encodeUtf8) - -- * Decoders -- |@@ -160,33 +147,6 @@ decB64BL = _implDecodingF (asUnexpected @"enc-B64" . BL64.decode) --- Kept for now but performance issues---- | WARNING (performance)------ @since 0.3.0.0-instance (UnexpectedDecodeErr f, Applicative f) => Decode f "enc-B64" "enc-B64" c T.Text where- decoding = decB64T---- |--- @since 0.3.0.0 -decB64T :: (UnexpectedDecodeErr f, Applicative f) => Decoding f "enc-B64" "enc-B64" c T.Text-decB64T = _implDecodingF (asUnexpected @"enc-B64" . fmap TE.decodeUtf8 . B64.decode . TE.encodeUtf8) -{-# WARNING decB64T "This method was not optimized for performance." #-}---- | WARNING (performance)------ @since 0.3.0.0 -instance (UnexpectedDecodeErr f, Applicative f) => Decode f "enc-B64" "enc-B64" c TL.Text where- decoding = decB64TL---- |--- @since 0.3.0.0 -decB64TL :: (UnexpectedDecodeErr f, Applicative f) => Decoding f "enc-B64" "enc-B64" c TL.Text-decB64TL = _implDecodingF (asUnexpected @"enc-B64" . fmap TEL.decodeUtf8 . BL64.decode . TEL.encodeUtf8) -{-# WARNING decB64TL "This method was not optimized for performance." #-}-- -- * Validation -- |@@ -199,27 +159,18 @@ instance (RecreateErr f, Applicative f) => Validate f "enc-B64" "enc-B64" c BL.ByteString where validation = validFromDec decB64BL --- |--- @since 0.3.0.0 -instance (RecreateErr f, Applicative f) => Validate f "enc-B64" "enc-B64" c T.Text where- validation = validFromDec decB64T --- |--- @since 0.3.0.0 -instance (RecreateErr f, Applicative f) => Validate f "enc-B64" "enc-B64" c TL.Text where- validation = validFromDec decB64TL- -- | Lenient decoding does not fail -- -- @since 0.3.0.0 instance Applicative f => Validate f "enc-B64-len" "enc-B64-len" c B.ByteString where- validation = mkValidation $ implTranP id+ validation = _mkValidation $ implTranP id -- | Lenient decoding does not fail -- -- @since 0.3.0.0 instance Applicative f => Validate f "enc-B64-len" "enc-B64-len" c BL.ByteString where- validation = mkValidation $ implTranP id+ validation = _mkValidation $ implTranP id
+ src/Data/TypedEncoding/Instances/Enc/Warn/Base64.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++-- | Defines /Base64/ encoding for Text+-- This version has poor performance.+--+-- @since 0.5.0.0+module Data.TypedEncoding.Instances.Enc.Warn.Base64 {-# WARNING "Not optimized for performance" #-} where++import Data.TypedEncoding+import Data.TypedEncoding.Instances.Support++import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Encoding as TE +import qualified Data.Text.Lazy.Encoding as TEL ++import qualified Data.ByteString.Base64 as B64+import qualified Data.ByteString.Base64.Lazy as BL64++-- | This instance will likely be removed in future versions (performance concerns)+-- (Moved from "Data.TypedEncoding.Instances.Enc.Base64")++-- @since 0.3.0.0+instance Applicative f => Encode f "enc-B64" "enc-B64" c T.Text where+ encoding = endB64T++-- | This function will likely be removed in future versions (performance concerns)+-- (Moved from "Data.TypedEncoding.Instances.Enc.Base64")+--+-- @since 0.3.0.0+endB64T :: Applicative f => Encoding f "enc-B64" "enc-B64" c T.Text+endB64T = _implEncodingP (TE.decodeUtf8 . B64.encode . TE.encodeUtf8) +++-- | +--+-- @since 0.3.0.0+instance (UnexpectedDecodeErr f, Applicative f) => Decode f "enc-B64" "enc-B64" c T.Text where+ decoding = decB64T++-- |+-- @since 0.3.0.0 +decB64T :: (UnexpectedDecodeErr f, Applicative f) => Decoding f "enc-B64" "enc-B64" c T.Text+decB64T = _implDecodingF (asUnexpected @"enc-B64" . fmap TE.decodeUtf8 . B64.decode . TE.encodeUtf8) ++-- | +--+-- @since 0.3.0.0 +instance (UnexpectedDecodeErr f, Applicative f) => Decode f "enc-B64" "enc-B64" c TL.Text where+ decoding = decB64TL++-- |+-- @since 0.3.0.0 +decB64TL :: (UnexpectedDecodeErr f, Applicative f) => Decoding f "enc-B64" "enc-B64" c TL.Text+decB64TL = _implDecodingF (asUnexpected @"enc-B64" . fmap TEL.decodeUtf8 . BL64.decode . TEL.encodeUtf8) ++-- |+-- @since 0.3.0.0 +instance (RecreateErr f, Applicative f) => Validate f "enc-B64" "enc-B64" c T.Text where+ validation = validFromDec decB64T++-- |+-- @since 0.3.0.0 +instance (RecreateErr f, Applicative f) => Validate f "enc-B64" "enc-B64" c TL.Text where+ validation = validFromDec decB64TL+
− src/Data/TypedEncoding/Instances/Restriction/Bool.hs
@@ -1,434 +0,0 @@--{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE AllowAmbiguousTypes #-}---- |--- Boolean algebra on encodings------ @since 0.2.1.0--- --- /(Experimental, early alpha development stage)/ ------ Use 'Data.TypedEncoding.Instances.Support.Bool' instead.--- --- This module was not converted to v0.3 style yet.------ == Grammar--- --- Simple grammar requires boolean terms to be included in parentheses------ @--- bool[BinaryOp]:(leftTerm)(rightTerm)--- bool[UnaryOp]:(term)--- @------ Expected behavior is described next to the corresponding combinator.------ @since 0.2.2.0-module Data.TypedEncoding.Instances.Restriction.Bool where ---import GHC.TypeLits-import Data.Proxy-import Data.Symbol.Ascii--import Data.TypedEncoding-import Data.TypedEncoding.Instances.Support-import Data.TypedEncoding.Instances.Support.Unsafe------ $setup--- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XTypeApplications--- >>> import qualified Data.Text as T--- >>> import Data.TypedEncoding.Instances.Restriction.Misc()----- |--- See examples in 'encBoolOrRight''-encBoolOrLeft :: forall f s t xs c str . (- BoolOpIs s "or" ~ 'True- -- IsBoolOr s ~ 'True- , Functor f- , LeftTerm s ~ t- ) => (Enc xs c str -> f (Enc (t ': xs) c str)) -> Enc xs c str -> f (Enc (s ': xs) c str) -encBoolOrLeft = implChangeAnn ---- |--- See examples in 'encBoolOrRight''-encBoolOrLeft' :: forall f s t xs c str . (- BoolOpIs s "or" ~ 'True- -- IsBoolOr s ~ 'True- , Functor f- , LeftTerm s ~ t- , Encode f t t c str- ) => Enc xs c str -> f (Enc (s ': xs) c str) -encBoolOrLeft' = encBoolOrLeft'' @t--encBoolOrLeft'' :: forall alg f s t xs c str . (- BoolOpIs s "or" ~ 'True- -- IsBoolOr s ~ 'True- , Functor f- , LeftTerm s ~ t- , Encode f t alg c str- ) => Enc xs c str -> f (Enc (s ': xs) c str) -encBoolOrLeft'' = encBoolOrLeft (encodeF' @alg @t @xs @f)---- |--- -encBoolOrRight :: forall f s t xs c str . (- BoolOpIs s "or" ~ 'True- -- IsBoolOr s ~ 'True- , Functor f- , RightTerm s ~ t- ) => (Enc xs c str -> f (Enc (t ': xs) c str)) -> Enc xs c str -> f (Enc (s ': xs) c str) -encBoolOrRight = implChangeAnn ---- |--- >>> :{ --- let tst1, tst2, tst3 :: Either EncodeEx (Enc '["boolOr:(r-Word8-decimal)(r-Int-decimal)"] () T.Text)--- tst1 = encBoolOrLeft' . toEncoding () $ "212" --- tst2 = encBoolOrRight' . toEncoding () $ "1000000" --- tst3 = encBoolOrLeft' . toEncoding () $ "1000000"--- :}--- --- >>> tst1 --- Right (UnsafeMkEnc Proxy () "212")------ >>> tst2--- Right (UnsafeMkEnc Proxy () "1000000")------ >>> tst3--- Left (EncodeEx "r-Word8-decimal" ("Payload does not satisfy format Word8-decimal: 1000000"))-encBoolOrRight' :: forall f s t xs c str . (- BoolOpIs s "or" ~ 'True- -- IsBoolOr s ~ 'True- , Functor f- , RightTerm s ~ t- , Encode f t t c str- ) => Enc xs c str -> f (Enc (s ': xs) c str) -encBoolOrRight' = encBoolOrRight'' @t--encBoolOrRight'' :: forall alg f s t xs c str . (- BoolOpIs s "or" ~ 'True- -- IsBoolOr s ~ 'True- , Functor f- , RightTerm s ~ t- , Encode f t alg c str- ) => Enc xs c str -> f (Enc (s ': xs) c str) -encBoolOrRight'' = encBoolOrRight (encodeF' @alg @t @xs @f) --encBoolAnd :: forall f s t1 t2 xs c str . (- BoolOpIs s "and" ~ 'True - , KnownSymbol s- -- IsBoolAnd s ~ 'True- , f ~ Either EncodeEx- , Eq str- , LeftTerm s ~ t1- , RightTerm s ~ t2- ) => - (Enc xs c str -> f (Enc (t1 ': xs) c str)) - -> (Enc xs c str -> f (Enc (t2 : xs) c str)) - -> Enc xs c str -> f (Enc (s ': xs) c str) -encBoolAnd fnl fnr en0 = - let - eent1 = fnl en0- eent2 = fnr en0- p = (Proxy :: Proxy s)- in - case (eent1, eent2) of- (Right ent1, Right ent2) -> - if getPayload ent1 == getPayload ent2- then Right . withUnsafeCoerce id $ ent1 - else Left $ EncodeEx p "Left - right encoding do not match" - (_, _) -> mergeErrs (emptyEncErr p) (mergeEncodeEx p) eent1 eent2---- |--- @"boolOr:(enc1)(enc2)"@ contains strings that encode the same way under both encodings.--- for example @"boolOr:(r-UPPER)(r-lower)"@ valid elements would include @"123-34"@ but not @"abc"@------ >>> :{--- let tst1, tst2 :: Either EncodeEx (Enc '["boolAnd:(r-Word8-decimal)(r-Int-decimal)"] () T.Text)--- tst1 = encBoolAnd' . toEncoding () $ "234"--- tst2 = encBoolAnd' . toEncoding () $ "100000"--- :}--- --- >>> tst1--- Right (UnsafeMkEnc Proxy () "234")--- >>> tst2--- Left (EncodeEx "r-Word8-decimal" ("Payload does not satisfy format Word8-decimal: 100000"))-encBoolAnd' :: forall s t1 t2 xs c str . (- BoolOpIs s "and" ~ 'True - , KnownSymbol s- -- IsBoolAnd s ~ 'True- , Eq str- , LeftTerm s ~ t1- , RightTerm s ~ t2- , Encode (Either EncodeEx) t1 t1 c str- , Encode (Either EncodeEx) t2 t2 c str- ) => Enc xs c str -> Either EncodeEx (Enc (s ': xs) c str) -encBoolAnd' = encBoolAnd'' @t1 @t2--encBoolAnd'' :: forall al1 al2 s t1 t2 xs c str . (- BoolOpIs s "and" ~ 'True - , KnownSymbol s- -- IsBoolAnd s ~ 'True- , Eq str- , LeftTerm s ~ t1- , RightTerm s ~ t2- , Encode (Either EncodeEx) t1 al1 c str- , Encode (Either EncodeEx) t2 al2 c str- ) => Enc xs c str -> Either EncodeEx (Enc (s ': xs) c str) -encBoolAnd'' = encBoolAnd (encodeF' @al1 @t1 @xs) (encodeF' @al2 @t2 @xs) ----- tst1, tst2 :: Either EncodeEx (Enc '["boolNot:(r-Word8-decimal)"] () T.Text)--- tst1 = encBoolNot' . toEncoding () $ "334"--- tst2 = encBoolNot' . toEncoding () $ "127"--encBoolNot :: forall s t xs c str . (- BoolOpIs s "not" ~ 'True- , KnownSymbol s- , FirstTerm s ~ t- , Restriction t - ) => (Enc xs c str -> Either EncodeEx (Enc (t ': xs) c str)) -> Enc xs c str -> Either EncodeEx (Enc (s ': xs) c str) -encBoolNot fn en0 = - let - een = fn en0- p = (Proxy :: Proxy s)- pt = (Proxy :: Proxy t)- in - case een of- Left _ -> Right . withUnsafeCoerce id $ en0- Right _ -> Left $ EncodeEx p $ "Encoding " ++ symbolVal pt ++ " succeeded" - ---- |--- >>> :{--- let tst1, tst2 :: Either EncodeEx (Enc '["boolNot:(r-Word8-decimal)"] () T.Text)--- tst1 = encBoolNot' . toEncoding () $ "334"--- tst2 = encBoolNot' . toEncoding () $ "127"--- :}------ >>> tst1--- Right (UnsafeMkEnc Proxy () "334")--- >>> tst2--- Left (EncodeEx "boolNot:(r-Word8-decimal)" ("Encoding r-Word8-decimal succeeded"))-encBoolNot' :: forall s t xs c str . (- BoolOpIs s "not" ~ 'True- , KnownSymbol s- , FirstTerm s ~ t- , KnownSymbol t- , Restriction t - , Encode (Either EncodeEx) t t c str- ) => Enc xs c str -> Either EncodeEx (Enc (s ': xs) c str) -encBoolNot' = encBoolNot'' @t--encBoolNot'' :: forall alg s t xs c str . (- BoolOpIs s "not" ~ 'True- , KnownSymbol s- , FirstTerm s ~ t- , Restriction t - , Encode (Either EncodeEx) t alg c str- ) => Enc xs c str -> Either EncodeEx (Enc (s ': xs) c str) -encBoolNot'' = encBoolNot (encodeF' @alg @t @xs)---- | --- Decodes boolean expression if all leaves are @"r-"@-decBoolR :: forall f xs t s c str . (- NestedR s ~ 'True- , Applicative f- ) => Enc (s ': xs) c str -> f (Enc xs c str) --decBoolR = implTranP id ---recWithEncBoolR :: forall (s :: Symbol) xs c str . (NestedR s ~ 'True) - => (Enc xs c str -> Either EncodeEx (Enc (s ': xs) c str)) - -> Enc xs c str -> Either RecreateEx (Enc (s ': xs) c str)-recWithEncBoolR = unsafeRecWithEncR--unsafeRecWithEncR :: forall (s :: Symbol) xs c str .- (Enc xs c str -> Either EncodeEx (Enc (s ': xs) c str)) - -> Enc xs c str -> Either RecreateEx (Enc (s ': xs) c str)-unsafeRecWithEncR fn = either (Left . encToRecrEx) Right . fn---- * Type family based parser ---- |--- >>> :kind! BoolOpIs "boolAnd:(someenc)(otherenc)" "and"--- ...--- = 'True-type family BoolOpIs (s :: Symbol) (op :: Symbol) :: Bool where- BoolOpIs s op = AcceptEq ('Text "Invalid bool encoding " ':<>: ShowType s ) (CmpSymbol (BoolOp s) op)---- | --- This works fast with @!kind@ but is much slower in declaration --- :kind! BoolOp "boolOr:()()"-type family BoolOp (s :: Symbol) :: Symbol where- BoolOp s = Fst (BoolOpHelper (Dupl s))- -- ToLower (TakeUntil (Drop 4 s) ":")--type family BoolOpHelper (x :: (Symbol, Symbol)) :: (Symbol, Bool) where- BoolOpHelper ('(,) s1 s2) = '(,) (ToLower (TakeUntil (Drop 4 s1) ":")) ( AcceptEq ('Text "Invalid bool encoding " ':<>: ShowType s2 ) (CmpSymbol "bool" (Take 4 s2)))---type family IsBool (s :: Symbol) :: Bool where- IsBool s = AcceptEq ('Text "Not boolean encoding " ':<>: ShowType s ) (CmpSymbol "bool" (Take 4 s))---- |--- --- >>> :kind! NestedR "boolOr:(r-abc)(r-cd)"--- ...--- = 'True------ >>> :kind! NestedR "boolOr:(boolAnd:(r-ab)(r-ac))(boolNot:(r-cd))"--- ...--- = 'True------ >>> :kind! NestedR "boolOr:(boolAnd:(r-ab)(ac))(boolNot:(r-cd))"--- ...--- ... (TypeError ...)--- ...-type family NestedR (s :: Symbol) :: Bool where- NestedR "" = 'True -- RightTerm, LeftTerm return "" on "r-"- NestedR s = Or (IsROrEmpty s) - (And (IsBool s) (And (NestedR (LeftTerm s)) (NestedR (RightTerm s)))) ---- Value level check------ nestedR :: String -> Bool--- nestedR s = isROrEmpty s || isBool s && (nestedR (leftTerm s) && nestedR (rightTerm s))---- isBool ('b' :'o' : 'o' : _) = True--- isBool _ = False---- isROrEmpty "" = True--- isROrEmpty ('r' : '-' : _) = True--- isROrEmpty _ = False---type family FirstTerm (s :: Symbol) :: Symbol where- FirstTerm s = LeftTerm s---- | --- returns "" for unary operator-type family SecondTerm (s :: Symbol) :: Symbol where- SecondTerm s = RightTerm s----- |--- >>> :kind! LeftTerm "boolSomeOp:(agag)(222)"--- ...--- = "agag"------ >>> :kind! LeftTerm "r-Int-decimal"--- ...--- = ""-type family LeftTerm (s :: Symbol) :: Symbol where- LeftTerm s = Concat (LDropLast( LTakeFstParen (LParenCnt (ToList s))))---- |--- >>> :kind! RightTerm "boolSomeOp:(agag)(222)"--- ...--- = "222"------ >>> :kind! RightTerm "r-Int-decimal"--- ...--- = ""-type family RightTerm (s :: Symbol) :: Symbol where- RightTerm s = Concat (LDropLast (LTakeSndParen 0 (LParenCnt (ToList s))))---type family LDropLast (s :: [Symbol]) :: [Symbol] where- LDropLast '[] = '[]- LDropLast '[x] = '[]- LDropLast (x ': xs) = x ': LDropLast xs---type family LParenCnt (s :: [Symbol]) :: [(Symbol, Nat)] where- LParenCnt '[] = '[]- LParenCnt ("(" ': xs) = LParenCntHelper ('(,) "(" 'Decr) (LParenCnt xs) -- '(,) "(" (LParenCntFstCnt (LParenCnt xs) - 1) ': LParenCnt xs- LParenCnt (")" ': xs) = LParenCntHelper ('(,) ")" 'Incr) (LParenCnt xs)- LParenCnt (x ': xs) = LParenCntHelper ('(,) x 'NoChng) (LParenCnt xs)--data Adjust = Incr | Decr | NoChng--type family AdjHelper (a :: Adjust) (n :: Nat) :: Nat where- AdjHelper 'Incr n = n + 1- AdjHelper 'Decr 0 = 0- AdjHelper 'Decr n = n - 1- AdjHelper 'NoChng n = n--type family LParenCntHelper (s :: (Symbol, Adjust)) (sx :: [(Symbol, Nat)]) :: [(Symbol, Nat)] where- LParenCntHelper ('(,) x k) '[] = '(,) x (AdjHelper k 0) ': '[]- LParenCntHelper ('(,) x k) ('(,) c i : xs) = '(,) x (AdjHelper k i) ': '(,) c i ': xs---type family LTakeFstParen (si :: [(Symbol, Nat)]) :: [Symbol] where - LTakeFstParen '[] = '[]- LTakeFstParen ('(,) _ 0 ': xs) = LTakeFstParen xs- LTakeFstParen ('(,) ")" 1 ': _) = '[")"]- LTakeFstParen ('(,) a p ': xs) = a ': LTakeFstParen xs---type family LTakeSndParen (n :: Nat) (si :: [(Symbol, Nat)]) :: [Symbol] where- LTakeSndParen _ '[] = '[]- LTakeSndParen 0 ('(,) ")" 1 ': xs) = LTakeSndParen 1 xs- LTakeSndParen 1 ('(,) _ 0 : xs) = LTakeSndParen 1 xs- LTakeSndParen 0 ('(,) _ _ ': xs) = LTakeSndParen 0 xs- LTakeSndParen 1 ('(,) a _ ': xs) = a : LTakeSndParen 1 xs- LTakeSndParen n _ = '[]---- -- * (Example) Value level equivalend of type family parsers----- -- map snd . parenCnt $ "((AGA)(bcd))(123) "--- -- dropLast . takeFstParen . parenCnt $ "((AGA)(bcd))(123)" --- -- dropLast . takeSndParen 0 . parenCnt $ "((AGA)(bcd))(123)" ---- leftTerm :: String -> String--- leftTerm = dropLast . takeFstParen . parenCnt---- rightTerm :: String -> String--- rightTerm = dropLast . takeSndParen 0 . parenCnt---- parenCnt :: String -> [(Char, Int)]--- parenCnt [] = []--- parenCnt ('(' : xs) = parenCntHelper ('(', -1) (parenCnt xs) --('(', parenCntFstCnt (parenCnt xs) - 1) : parenCnt xs--- parenCnt (')' : xs) = parenCntHelper (')', 1) (parenCnt xs) -- (')', parenCntFstCnt (parenCnt xs) + 1) : parenCnt xs--- parenCnt (x : xs) = parenCntHelper (x, 0) (parenCnt xs) -- (x, parenCntFstCnt (parenCnt xs) ) : parenCnt xs----- parenCntHelper :: (Char, Int) -> [(Char, Int)] -> [(Char, Int)]--- parenCntHelper (x, k) [] = [(x,k)]--- parenCntHelper (x, k) ((c,i) : xs) = (x, i + k): (c,i) : xs----- takeFstParen :: [(Char, Int)] -> [Char]--- takeFstParen [] = []--- takeFstParen ((_, 0) : xs) = takeFstParen xs--- takeFstParen ((')', 1) : _) = [')']--- takeFstParen ((a, p) : xs) = a : takeFstParen xs---- takeSndParen :: Int -> [(Char, Int)] -> [Char]--- takeSndParen _ [] = []--- takeSndParen 0 ((')', 1) : xs) = takeSndParen 1 xs--- takeSndParen 1 ((_, 0) : xs) = takeSndParen 1 xs--- takeSndParen 0 ((_, _) : xs) = takeSndParen 0 xs--- takeSndParen 1 ((a, _) : xs) = a : takeSndParen 1 xs--- takeSndParen _ _ = []---- dropLast :: [Char] -> [Char]--- dropLast [] = []--- dropLast [x] = []--- dropLast (x:xs) = x : dropLast xs-
src/Data/TypedEncoding/Instances/Restriction/CHAR8.hs view
@@ -9,11 +9,11 @@ -- | ----- Should not be used directly, only as superset+-- "r-CHAR8" should not be used directly, only as superset. ----- Checks if all chars are @< \'\256\'@+-- This module includes tests that verify that all chars are @< \'\256\'@ ----- Encoding functions are here for test support only, no instances+-- Encoding functions are here for test support only, no instances. -- -- @since 0.3.1.0 module Data.TypedEncoding.Instances.Restriction.CHAR8 where
src/Data/TypedEncoding/Instances/Restriction/D76.hs view
@@ -8,13 +8,16 @@ {-# LANGUAGE ScopedTypeVariables #-} -- | --- Checks that satisfy D76 Unicode standard (/text/ replaces chars that are in range--- U+D800 to U+DFFF inclusive)+-- "r-UNICODE.D76" restricts Unicode characters by excluding the range U+D800 to U+DFFF. ----- Note, no IsSuperset "r-UNICODE.D76" "r-CHAR8" mapping even though the numeric range of D76 includes all CHAR8 bytes.+-- This is important because the commonly used @Text@ type from /text/ package replaces chars that are in range+-- U+D800 to U+DFFF (inclusive).+--+-- Note, there is no @IsSuperset "r-UNICODE.D76" "r-CHAR8"@ mapping even though the numeric range of D76 includes all CHAR8 bytes. -- This is more /nominal/ decision that prevents certain unwanted conversions from being possible. ----- Similarly no IsSuperset "r-UNICODE.D76" "r-ByteRep", this annotation acts as a guard to what can go into @Text@.+-- Similarly there is no IsSuperset "r-UNICODE.D76" "r-ByteRep", "r-UNICODE.D76" acts as a guard to what can go into @Text@+-- and this prevents some unwanted conversions. -- -- @since 0.4.0.0 module Data.TypedEncoding.Instances.Restriction.D76 where
src/Data/TypedEncoding/Instances/Restriction/Misc.hs view
@@ -10,13 +10,13 @@ -- | Common /restriction/ "r-" instances ----- Before v0.3 @Data.TypedEncoding.Instances.Restriction.Common@+-- Renamed from @Data.TypedEncoding.Instances.Restriction.Common@ (v0.3) -- -- @since 0.2.0.0 module Data.TypedEncoding.Instances.Restriction.Misc where import Data.Word-import Data.Functor.Identity+-- import Data.Functor.Identity import Data.String import Data.Proxy import Text.Read@@ -27,18 +27,15 @@ -- $setup -- >>> import qualified Data.Text as T -instance IsString str => ToEncString Identity "r-()" "r-()" () str where- toEncF _ = Identity $ UnsafeMkEnc Proxy () (fromString "()") - instance (IsStringR str) => Encode (Either EncodeEx) "r-Word8-decimal" "r-Word8-decimal" c str where encoding = encWord8Dec instance (Applicative f) => Decode f "r-Word8-decimal" "r-Word8-decimal" c str where decoding = decAnyR instance (IsStringR str) => Validate (Either RecreateEx) "r-Word8-decimal" "r-Word8-decimal" c str where validation = validR encWord8Dec-instance IsString str => ToEncString Identity "r-Word8-decimal" "r-Word8-decimal" Word8 str where- toEncF i = Identity $ UnsafeMkEnc Proxy () (fromString . show $ i)+instance (IsString str, Applicative f) => ToEncString f "r-Word8-decimal" "r-Word8-decimal" Word8 str where+ toEncF i = pure $ UnsafeMkEnc Proxy () (fromString . show $ i) instance (IsStringR str, UnexpectedDecodeErr f, Applicative f) => FromEncString f "r-Word8-decimal" "r-Word8-decimal" Word8 str where fromEncF = asUnexpected @ "r-Word8-decimal" . readEither . toString . getPayload @@ -52,8 +49,8 @@ decoding = decAnyR instance (IsStringR str) => Validate (Either RecreateEx) "r-Int-decimal" "r-Int-decimal" c str where validation = validR encIntDec-instance IsString str => ToEncString Identity "r-Int-decimal" "r-Int-decimal" Int str where- toEncF i = Identity $ UnsafeMkEnc Proxy () (fromString . show $ i)+instance (IsString str, Applicative f) => ToEncString f "r-Int-decimal" "r-Int-decimal" Int str where+ toEncF i = pure $ UnsafeMkEnc Proxy () (fromString . show $ i) encIntDec :: (IsStringR str) => Encoding (Either EncodeEx) "r-Int-decimal" "r-Int-decimal" c str encIntDec = _implEncodingEx (verifyWithRead @Int "Int-decimal")
src/Data/TypedEncoding/Instances/Restriction/UTF8.hs view
@@ -35,7 +35,6 @@ -- >>> import Test.QuickCheck.Instances.Text() -- >>> import Test.QuickCheck.Instances.ByteString() -- >>> import Data.TypedEncoding--- >>> import Data.TypedEncoding.Internal.Util (proxiedId) -- >>> let emptyUTF8B = unsafeSetPayload () "" :: Enc '["r-UTF8"] () B.ByteString -- >>> :{ -- instance Arbitrary (Enc '["r-UTF8"] () B.ByteString) where @@ -81,7 +80,6 @@ -- using lazy decoding to detect errors seems to be the fastest option that is not super hard to code--- TODO v0.4.1 test performance encUTF8B :: Encoding (Either EncodeEx) "r-UTF8" "r-UTF8" c B.ByteString encUTF8B = _implEncodingEx (implVerifyR (TEL.decodeUtf8' . BL.fromStrict))
src/Data/TypedEncoding/Instances/Support.hs view
@@ -10,7 +10,6 @@ -- * Classes , module Data.TypedEncoding.Common.Class -- * Combinators- , module Data.TypedEncoding.Instances.Support.Common , module Data.TypedEncoding.Instances.Support.Helpers , module Data.TypedEncoding.Instances.Support.Encode , module Data.TypedEncoding.Instances.Support.Decode@@ -20,7 +19,6 @@ , module Data.TypedEncoding.Common.Util.TypeLits ) where -import Data.TypedEncoding.Instances.Support.Common import Data.TypedEncoding.Instances.Support.Helpers import Data.TypedEncoding.Instances.Support.Encode import Data.TypedEncoding.Instances.Support.Decode
− src/Data/TypedEncoding/Instances/Support/Common.hs
@@ -1,42 +0,0 @@--{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeApplications #-}---- | Exports for instance creation.--- --- Contains typical things needed when implementing--- encoding, decoding, recreate, or type to string conversions.-module Data.TypedEncoding.Instances.Support.Common where--import Data.TypedEncoding.Instances.Support.Unsafe-import Data.TypedEncoding.Common.Types-import Data.Proxy---- $setup--- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XTypeApplications----- * Decoding ---- | Universal decoding for all "r-" types------ @since 0.3.0.0-decAnyR :: forall r f c str . (Restriction r, Applicative f) => Decoding f r r c str-decAnyR = decAnyR' @r @r---- |--- @since 0.3.0.0-decAnyR' :: forall alg r f c str . (Restriction r, Applicative f) => Decoding f r alg c str-decAnyR' = UnsafeMkDecoding Proxy (implTranP id) ---- |--- @since 0.3.0.0-decAnyR_ :: forall r f c str alg . (Restriction r, Algorithm r alg, Applicative f) => Decoding f r alg c str-decAnyR_ = mkDecoding $ implTranP id-
src/Data/TypedEncoding/Instances/Support/Decode.hs view
@@ -3,12 +3,12 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}--- {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-} --- | v0.2 style decoding combinators+-- | Common decoding combinators -- -- @since 0.3.0.0 module Data.TypedEncoding.Instances.Support.Decode where@@ -18,15 +18,34 @@ import Data.Proxy import Data.TypedEncoding.Common.Types +-- * Universal decoding for all "r-" types +-- | +--+-- @since 0.3.0.0+decAnyR :: forall r f c str . (Restriction r, Applicative f) => Decoding f r r c str+decAnyR = decAnyR' @r @r +-- |+-- @since 0.3.0.0+decAnyR' :: forall alg r f c str . (Restriction r, Applicative f) => Decoding f r alg c str+decAnyR' = UnsafeMkDecoding Proxy (implTranP id) ++-- |+-- @since 0.3.0.0+decAnyR_ :: forall r f c str alg . (Restriction r, Algorithm r alg, Applicative f) => Decoding f r alg c str+decAnyR_ = _mkDecoding $ implTranP id+++-- * v0.2 style decoding combinators+ -- * Compiler figure out algorithm, these appear fast enough _implDecodingF :: forall nm f c str . Functor f => (str -> f str) -> Decoding f nm (AlgNm nm) c str-_implDecodingF f = mkDecoding $ implTranF f+_implDecodingF f = _mkDecoding $ implTranF f _implDecodingConfF :: forall nm f c str . Functor f => (c -> str -> f str) -> Decoding f nm (AlgNm nm) c str-_implDecodingConfF f = mkDecoding $ implTranF' f+_implDecodingConfF f = _mkDecoding $ implTranF' f -- * Assume @alg ~ nm@ or explicit @alg@
src/Data/TypedEncoding/Instances/Support/Helpers.hs view
@@ -8,11 +8,12 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleContexts #-} --- | Support for mostly creating instances ToEncString and FromEncString conversions+-- | Various helper functions.+-- There are mostly for for creating @ToEncString@ and @FromEncString@ instances module Data.TypedEncoding.Instances.Support.Helpers where -import Data.String+-- import Data.String import Data.Proxy import Text.Read import Data.TypedEncoding.Common.Types@@ -39,13 +40,6 @@ => c -> (s1 -> s2 -> s2) -> s2 -> f (Enc xs1 c s1) -> Enc xs2 c s2 foldEnc c f sinit = unsafeSetPayload c . foldr f sinit . fmap getPayload --- | Similar to 'foldEnc', assumes that destination payload has @IsString@ instance and uses @""@ as base case. ------ @since 0.2.0.0-foldEncStr :: forall (xs2 :: [Symbol]) (xs1 :: [Symbol]) f c s1 s2 - . (Foldable f, Functor f, IsString s2) - => c -> (s1 -> s2 -> s2) -> f (Enc xs1 c s1) -> Enc xs2 c s2-foldEncStr c f = foldEnc c f "" -- | Similar to 'foldEnc', works with untyped 'CheckedEnc' --@@ -55,16 +49,11 @@ => c -> ([EncAnn] -> s1 -> s2 -> s2) -> s2 -> f (CheckedEnc c s1) -> Enc xs2 c s2 foldCheckedEnc c f sinit = unsafeSetPayload c . foldr (uncurry f) sinit . fmap getCheckedEncPayload --- | Similar to 'foldEncStr', works with untyped 'CheckedEnc'------ @since 0.2.0.0-foldCheckedEncStr :: forall (xs2 :: [Symbol]) f c s1 s2 . (Foldable f, Functor f, IsString s2) => c -> ([EncAnn] -> s1 -> s2 -> s2) -> f (CheckedEnc c s1) -> Enc xs2 c s2-foldCheckedEncStr c f = foldCheckedEnc c f "" -- * Composite encoding: Recreate and Encode helpers --- | Splits composite payload into homogenious chunks+-- | Splits composite payload into homogeneous chunks -- -- @since 0.2.0.0 splitPayload :: forall (xs2 :: [Symbol]) (xs1 :: [Symbol]) c s1 s2 . @@ -75,12 +64,13 @@ -- | Untyped version of 'splitPayload' ----- @since 0.2.0.0-splitSomePayload :: forall c s1 s2 . +-- (renamed from @splitCheckedPayload@ in previous versions)+-- @since 0.5.0.0+splitCheckedPayload :: forall c s1 s2 . ([EncAnn] -> s1 -> [([EncAnn], s2)]) -> CheckedEnc c s1 -> [CheckedEnc c s2]-splitSomePayload f (UnsafeMkCheckedEnc ann1 c s1) = map (\(ann2, s2) -> UnsafeMkCheckedEnc ann2 c s2) (f ann1 s1)+splitCheckedPayload f (UnsafeMkCheckedEnc ann1 c s1) = map (\(ann2, s2) -> UnsafeMkCheckedEnc ann2 c s2) (f ann1 s1) -- * Utility combinators @@ -108,14 +98,14 @@ -- | Convenience function for checking if @str@ decodes without error--- using @enc@ encoding markers and decoders that can pick decoder based+-- using @dec@ encoding markers and decoders that can pick decoder based -- on that marker -- -- @since 0.3.0.0-verifyDynEnc :: forall s str err1 err2 enc a. (KnownSymbol s, Show err1, Show err2) => +verifyDynEnc :: forall s str err1 err2 dec a. (KnownSymbol s, Show err1, Show err2) => Proxy s -- ^ proxy defining encoding annotation- -> (Proxy s -> Either err1 enc) -- ^ finds encoding marker @enc@ for given annotation or fails- -> (enc -> str -> Either err2 a) -- ^ decoder based on @enc@ marker+ -> (Proxy s -> Either err1 dec) -- ^ finds encoding marker @dec@ for given annotation or fails+ -> (dec -> str -> Either err2 a) -- ^ decoder based on @dec@ marker -> str -- ^ input -> Either EncodeEx str verifyDynEnc p findenc decoder str =
src/Data/TypedEncoding/Instances/Support/Unsafe.hs view
@@ -10,6 +10,7 @@ -- | Direct use of these methods is discouraged. -- Use "Data.TypedEncoding.Instances.Support.Encode" or "Data.TypedEncoding.Instances.Support.Decode" +-- instead. module Data.TypedEncoding.Instances.Support.Unsafe where import Data.Proxy
src/Data/TypedEncoding/Instances/Support/Validate.hs view
@@ -8,10 +8,8 @@ {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TypeApplications #-} --- | Exports for instance creation.--- --- Contains typical things needed when implementing--- encoding, decoding, recreate, or type to string conversions.+-- | +-- Convenience validation utilities. module Data.TypedEncoding.Instances.Support.Validate where import Data.TypedEncoding.Common.Types import Data.TypedEncoding.Common.Class @@ -45,14 +43,13 @@ validR = validRFromEnc' @nm @nm --- TODO rename for consistency to _- -- | Can cause slow compilation if used--- --- @since 0.3.0.0-validR' :: forall nm f c str alg . (Restriction nm, Algorithm nm alg, KnownSymbol nm, RecreateErr f, Applicative f) => Encoding (Either EncodeEx) nm alg c str -> Validation f nm alg c str -validR' = validRFromEnc' @alg @nm -+--+-- (renamed from validR defined in pre 0.5 versions)+--+-- @since 0.5.0.0+_validR :: forall nm f c str alg . (Restriction nm, Algorithm nm alg, KnownSymbol nm, RecreateErr f, Applicative f) => Encoding (Either EncodeEx) nm alg c str -> Validation f nm alg c str +_validR = validRFromEnc' @alg @nm -- |@@ -60,18 +57,10 @@ -- -- @since 0.3.0.0 validFromEnc' :: forall alg nm f c str . (KnownSymbol nm, RecreateErr f, Applicative f) => Encoding (Either EncodeEx) nm alg c str -> Validation f nm alg c str -validFromEnc' (UnsafeMkEncoding p fn) = UnsafeMkValidation p (encAsRecreateErr . rfn) - where- encAsRecreateErr :: Either EncodeEx a -> f a- encAsRecreateErr (Left (EncodeEx p err)) = recoveryErr $ RecreateEx p err- encAsRecreateErr (Right r) = pure r - rfn :: forall (xs :: [Symbol]) . Enc (nm ': xs) c str -> Either EncodeEx (Enc xs c str)- rfn (UnsafeMkEnc _ conf str) = - let re = fn $ UnsafeMkEnc Proxy conf str- in UnsafeMkEnc Proxy conf . getPayload <$> re -+validFromEnc' = validRFromEnc'+ -{-# DEPRECATED validFromEnc' "Use validR' instead (valid for r- encodings only)" #-}+{-# DEPRECATED validFromEnc' "Use _validR instead (valid for r- encodings only)" #-} validRFromEnc' :: forall alg nm f c str . (KnownSymbol nm, RecreateErr f, Applicative f) => Encoding (Either EncodeEx) nm alg c str -> Validation f nm alg c str
src/Data/TypedEncoding/Internal/Util.hs view
@@ -1,26 +1,16 @@ -{-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE RankNTypes #-} ++ module Data.TypedEncoding.Internal.Util where -import Data.Proxy-import GHC.TypeLits explainBool :: (a -> err) -> (a, Bool) -> Either err a explainBool _ (a, True) = Right a explainBool f (a, False) = Left $ f a --- | Sometimes is easier to pass around a proxy than do TypeApplications-proxiedId :: Proxy a -> a -> a-proxiedId _ = id---- | explicit mapM-extractEither :: Traversable t => t (Either err a) -> Either err (t a)-extractEither = sequence -- mapM id+-- -- | explicit mapM+-- extractEither :: Traversable t => t (Either err a) -> Either err (t a)+-- extractEither = sequence -- mapM id -withSomeSymbol :: SomeSymbol -> (forall x. KnownSymbol x => Proxy x -> r) -> r-withSomeSymbol s fn = case s of - SomeSymbol p -> fn p
src/Examples/TypedEncoding.hs view
@@ -4,15 +4,21 @@ -- * Conversions between encodings , module Examples.TypedEncoding.Conversions -- * Adding new encodings, error handling - , module Examples.TypedEncoding.DiySignEncoding+ , module Examples.TypedEncoding.Instances.DiySignEncoding+ -- * Examples of "do-" encodings that perform some string transformation such as title-casing + , module Examples.TypedEncoding.Instances.Do.Sample -- * Converting other types to and from encoded strings , module Examples.TypedEncoding.ToEncString -- * Modifying encoded payload - , module Examples.TypedEncoding.Unsafe + , module Examples.TypedEncoding.Unsafe+ -- * a more dependently typed alternative to @CheckedEnc@+ , module Examples.TypedEncoding.SomeEnc ) where import Examples.TypedEncoding.Overview import Examples.TypedEncoding.Conversions -import Examples.TypedEncoding.DiySignEncoding +import Examples.TypedEncoding.Instances.DiySignEncoding +import Examples.TypedEncoding.Instances.Do.Sample import Examples.TypedEncoding.Unsafe import Examples.TypedEncoding.ToEncString +import Examples.TypedEncoding.SomeEnc
src/Examples/TypedEncoding/Conversions.hs view
@@ -30,7 +30,7 @@ -- -- Conversions aim at providing type safety when moving between encoded string-like types. ----- __The assumption__ made by `typed-encoding` is that @"enc-"@ encodings work in an equivalent way independently of the payload type.+-- __The assumption__ made by /typed-encoding/ is that @"enc-"@ encodings work in an equivalent way independently of the payload type. -- For example, if the following instances exist: -- -- @
− src/Examples/TypedEncoding/DiySignEncoding.hs
@@ -1,130 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}---- {-# LANGUAGE PartialTypeSignatures #-}---- | Simple DIY encoding example that "signs" Text with its length.------ Documentation includes discussion of error handling options. ------ My current thinking: ------ Stronger type level information about encoding provides type safety over decoding process.--- Decoding cannot fail unless somehow underlying data has been corrupted.------ Such integrity of data should be enforced at boundaries--- (JSON instances, DB retrievals, etc). This can be accomplished using provided support for /Validation/ or using 'Data.TypedEncoding.Common.Types.UncheckedEnc.UncheckedEnc'.--- --- This still is user decision, the errors during decoding process are considered unexpected 'UnexpectedDecodeErr'.--- In particular user can decide to use unsafe operations with the encoded type. See 'Examples.TypedEncoding.Unsafe'.--module Examples.TypedEncoding.DiySignEncoding where--import Data.TypedEncoding-import qualified Data.TypedEncoding.Instances.Support as EnT--import qualified Data.Text as T-import Data.Char-import Data.Semigroup ((<>))-import Text.Read (readMaybe)---- $setup--- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds--- >>> import Test.QuickCheck.Instances.Text()---- | encoding function, typically should be module private -encodeSign :: T.Text -> T.Text-encodeSign t = (T.pack . show . T.length $ t) <> ":" <> t----- | dual purpose decoding and recovery function.------ This typically should be module private.------ >>> decodeSign "3:abc" --- Right "abc"------ >>> decodeSign "4:abc" --- Left "Corrupted Signature"-decodeSign :: T.Text -> Either String T.Text-decodeSign t = - let (sdit, rest) = T.span isDigit $ t- actsize = T.length rest - 1- msize = readMaybe . T.unpack $ sdit- checkDelimit = T.isInfixOf ":" rest- in if msize == Just actsize && checkDelimit- then Right $ T.drop 1 rest- else Left $ "Corrupted Signature" ----- | Encoded hello world example.------ >>> helloSigned--- UnsafeMkEnc Proxy () "11:Hello World"------ >>> fromEncoding . decodeAll $ helloSigned --- "Hello World"-helloSigned :: Enc '["my-sign"] () T.Text-helloSigned = encodeAll . toEncoding () $ "Hello World"---- | property checks that 'T.Text' values are expected to decode --- without error after encoding.------ prop> \t -> propEncDec-propEncDec :: T.Text -> Bool-propEncDec t = - let enc = encodeAll . toEncoding () $ t :: Enc '["my-sign"] () T.Text- in t == (fromEncoding . decodeAll $ enc)--hacker :: Either RecreateEx (Enc '["my-sign"] () T.Text)-hacker = - let payload = getPayload $ helloSigned :: T.Text- -- | payload is sent over network and get corrupted- newpay = payload <> " corruption" - -- | boundary check recovers the data- newdata = recreateFAll . toEncoding () $ newpay :: Either RecreateEx (Enc '["my-sign"] () T.Text)- in newdata --- ^ Hacker example--- The data was transmitted over a network and got corrupted.------ >>> let payload = getPayload $ helloSigned :: T.Text--- >>> let newpay = payload <> " corruption" --- >>> recreateFAll . toEncoding () $ newpay :: Either RecreateEx (Enc '["my-sign"] () T.Text)--- Left (RecreateEx "my-sign" ("Corrupted Signature"))------ >>> recreateFAll . toEncoding () $ payload :: Either RecreateEx (Enc '["my-sign"] () T.Text)--- Right (UnsafeMkEnc Proxy () "11:Hello World")----- | Because encoding function is pure we can create instance of 'Encode' --- that is polymorphic in effect @f@. ------ This is done using 'EnT.implTranP' combinator.-instance Applicative f => Encode f "my-sign" "my-sign" c T.Text where- encoding = EnT._implEncodingP encodeSign ---- | Decoding allows effectful @f@ to allow for troubleshooting and unsafe payload changes.------ Implementation simply uses 'EnT.implDecodingF' combinator on the 'asUnexpected' composed with decoding function.------ 'UnexpectedDecodeErr' has Identity instance allowing for decoding that assumes errors are not possible.------ For debugging purposes or when unsafe changes to "my-sign" @Error UnexpectedDecodeEx@ instance can be used.-instance (UnexpectedDecodeErr f, Applicative f) => Decode f "my-sign" "my-sign" c T.Text where- decoding = decMySign --decMySign :: (UnexpectedDecodeErr f, Applicative f) => Decoding f "my-sign" "my-sign" c T.Text-decMySign = EnT.implDecodingF (asUnexpected @"my-sign" . decodeSign) ---- | Recreation allows effectful @f@ to check for tampering with data.------ Implementation simply uses 'EnT.validFromDec' combinator on the recovery function.-instance (RecreateErr f, Applicative f) => Validate f "my-sign" "my-sign" c T.Text where- validation = EnT.validFromDec decMySign-
+ src/Examples/TypedEncoding/Instances/DiySignEncoding.hs view
@@ -0,0 +1,130 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- {-# LANGUAGE PartialTypeSignatures #-}++-- | Simple DIY encoding example that "signs" Text with its length.+--+-- Documentation includes discussion of error handling options. +--+-- My current thinking: +--+-- Stronger type level information about encoding provides type safety over decoding process.+-- Decoding cannot fail unless somehow underlying data has been corrupted.+--+-- Such integrity of data should be enforced at boundaries+-- (JSON instances, DB retrievals, etc). This can be accomplished using provided support for /Validation/ or using 'Data.TypedEncoding.Common.Types.UncheckedEnc.UncheckedEnc'.+-- +-- This still is user decision, the errors during decoding process are considered unexpected 'UnexpectedDecodeErr'.+-- In particular user can decide to use unsafe operations with the encoded type. See 'Examples.TypedEncoding.Unsafe'.++module Examples.TypedEncoding.Instances.DiySignEncoding where++import Data.TypedEncoding+import qualified Data.TypedEncoding.Instances.Support as EnT++import qualified Data.Text as T+import Data.Char+import Data.Semigroup ((<>))+import Text.Read (readMaybe)++-- $setup+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds+-- >>> import Test.QuickCheck.Instances.Text()++-- | encoding function, typically should be module private +encodeSign :: T.Text -> T.Text+encodeSign t = (T.pack . show . T.length $ t) <> ":" <> t+++-- | dual purpose decoding and recovery function.+--+-- This typically should be module private.+--+-- >>> decodeSign "3:abc" +-- Right "abc"+--+-- >>> decodeSign "4:abc" +-- Left "Corrupted Signature"+decodeSign :: T.Text -> Either String T.Text+decodeSign t = + let (sdit, rest) = T.span isDigit $ t+ actsize = T.length rest - 1+ msize = readMaybe . T.unpack $ sdit+ checkDelimit = T.isInfixOf ":" rest+ in if msize == Just actsize && checkDelimit+ then Right $ T.drop 1 rest+ else Left $ "Corrupted Signature" +++-- | Encoded hello world example.+--+-- >>> helloSigned+-- UnsafeMkEnc Proxy () "11:Hello World"+--+-- >>> fromEncoding . decodeAll $ helloSigned +-- "Hello World"+helloSigned :: Enc '["my-sign"] () T.Text+helloSigned = encodeAll . toEncoding () $ "Hello World"++-- | property checks that 'T.Text' values are expected to decode +-- without error after encoding.+--+-- prop> \t -> propEncDec+propEncDec :: T.Text -> Bool+propEncDec t = + let enc = encodeAll . toEncoding () $ t :: Enc '["my-sign"] () T.Text+ in t == (fromEncoding . decodeAll $ enc)++hacker :: Either RecreateEx (Enc '["my-sign"] () T.Text)+hacker = + let payload = getPayload $ helloSigned :: T.Text+ -- | payload is sent over network and get corrupted+ newpay = payload <> " corruption" + -- | boundary check recovers the data+ newdata = recreateFAll . toEncoding () $ newpay :: Either RecreateEx (Enc '["my-sign"] () T.Text)+ in newdata +-- ^ Hacker example+-- The data was transmitted over a network and got corrupted.+--+-- >>> let payload = getPayload $ helloSigned :: T.Text+-- >>> let newpay = payload <> " corruption" +-- >>> recreateFAll . toEncoding () $ newpay :: Either RecreateEx (Enc '["my-sign"] () T.Text)+-- Left (RecreateEx "my-sign" ("Corrupted Signature"))+--+-- >>> recreateFAll . toEncoding () $ payload :: Either RecreateEx (Enc '["my-sign"] () T.Text)+-- Right (UnsafeMkEnc Proxy () "11:Hello World")+++-- | Because encoding function is pure we can create instance of 'Encode' +-- that is polymorphic in effect @f@. +--+-- This is done using 'EnT.implTranP' combinator.+instance Applicative f => Encode f "my-sign" "my-sign" c T.Text where+ encoding = EnT._implEncodingP encodeSign ++-- | Decoding allows effectful @f@ to allow for troubleshooting and unsafe payload changes.+--+-- Implementation simply uses 'EnT.implDecodingF' combinator on the 'asUnexpected' composed with decoding function.+--+-- 'UnexpectedDecodeErr' has Identity instance allowing for decoding that assumes errors are not possible.+--+-- For debugging purposes or when unsafe changes to "my-sign" @Error UnexpectedDecodeEx@ instance can be used.+instance (UnexpectedDecodeErr f, Applicative f) => Decode f "my-sign" "my-sign" c T.Text where+ decoding = decMySign ++decMySign :: (UnexpectedDecodeErr f, Applicative f) => Decoding f "my-sign" "my-sign" c T.Text+decMySign = EnT.implDecodingF (asUnexpected @"my-sign" . decodeSign) ++-- | Recreation allows effectful @f@ to check for tampering with data.+--+-- Implementation simply uses 'EnT.validFromDec' combinator on the recovery function.+instance (RecreateErr f, Applicative f) => Validate f "my-sign" "my-sign" c T.Text where+ validation = EnT.validFromDec decMySign+
+ src/Examples/TypedEncoding/Instances/Do/Sample.hs view
@@ -0,0 +1,81 @@++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- | This module defines some example "do-" encodings+-- +-- See "Examples.TypedEncoding.Overview" for usage examples.+-- +-- (moved from @Data.TypedEncoding.Instances.Do.Sample@)+--+-- @since 0.5.0.0+module Examples.TypedEncoding.Instances.Do.Sample where++import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.ByteString as B++import Data.Char++import Data.TypedEncoding.Instances.Support+import Data.TypedEncoding.Instances.Support.Unsafe+import Examples.TypedEncoding.Util (HasA (..))+-- |+-- @since 0.3.0.0 +instance Applicative f => Encode f "do-UPPER" "do-UPPER" c T.Text where+ encoding = _implEncodingP T.toUpper++instance (RecreateErr f, Applicative f) => Validate f "do-UPPER" "do-UPPER" c T.Text where+ validation = _mkValidation $+ implTranF (asRecreateErr @"do-UPPER" . (\t -> + let (g,b) = T.partition isUpper t+ in if T.null b+ then Right t+ else Left $ "Found not upper case chars " ++ T.unpack b)+ )++instance Applicative f => Encode f "do-UPPER" "do-UPPER" c TL.Text where+ encoding = _implEncodingP TL.toUpper+++-- |+-- @since 0.3.0.0 +instance Applicative f => Encode f "do-lower" "do-lower" c T.Text where+ encoding = _implEncodingP T.toLower ++instance Applicative f => Encode f "do-lower" "do-lower" c TL.Text where+ encoding = _implEncodingP TL.toLower ++-- |+-- @since 0.3.0.0 +instance Applicative f => Encode f "do-Title" "do-Title" c T.Text where+ encoding = _implEncodingP T.toTitle ++instance Applicative f => Encode f "do-Title" "do-Title" c TL.Text where+ encoding = _implEncodingP TL.toTitle ++-- |+-- @since 0.3.0.0 +instance Applicative f => Encode f "do-reverse" "do-reverse" c T.Text where+ encoding = _implEncodingP T.reverse +instance Applicative f => Encode f "do-reverse" "do-reverse" c TL.Text where+ encoding = _implEncodingP TL.reverse ++-- |+-- @since 0.1.0.0+newtype SizeLimit = SizeLimit {unSizeLimit :: Int} deriving (Eq, Show)++-- |+-- @since 0.3.0.0 +instance (HasA SizeLimit c, Applicative f) => Encode f "do-size-limit" "do-size-limit" c T.Text where+ encoding = _implEncodingConfP (T.take . unSizeLimit . has @ SizeLimit) +instance (HasA SizeLimit c, Applicative f) => Encode f "do-size-limit" "do-size-limit" c B.ByteString where+ encoding = _implEncodingConfP (B.take . unSizeLimit . has @ SizeLimit) +
src/Examples/TypedEncoding/Overview.hs view
@@ -3,8 +3,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeApplications #-} --- {-# LANGUAGE PartialTypeSignatures #-}--- {-# OPTIONS_GHC -Wno-partial-type-signatures #-}+{-# OPTIONS_GHC -Wno-deprecations #-} -- | type-encoding overview examples. --@@ -16,15 +15,17 @@ -- -- * "Data.TypedEncoding.Instances.Enc.Base64" -- * "Data.TypedEncoding.Instances.Restriction.ASCII"--- * "Data.TypedEncoding.Instances.Do.Sample"+-- * "Examples.TypedEncoding.Instances.Do.Sample" -- module Examples.TypedEncoding.Overview where import Data.TypedEncoding import Data.TypedEncoding.Instances.Enc.Base64 ()+import Data.TypedEncoding.Instances.Enc.Warn.Base64 () import Data.TypedEncoding.Instances.Restriction.ASCII ()-import Data.TypedEncoding.Instances.Do.Sample+import Examples.TypedEncoding.Instances.Do.Sample+import Examples.TypedEncoding.Util (HasA (..)) import qualified Data.ByteString as B import qualified Data.Text as T@@ -151,7 +152,7 @@ -- * "do-" Encodings -- |--- "do-UPPER" (from 'Data.TypedEncoding.Instances.Do.Sample' module) encoding applied to "Hello World"+-- "do-UPPER" (from 'Examples.TypedEncoding.Instances.Do.Sample' module) encoding applied to "Hello World" -- -- Notice a namespace thing going on, "enc-" is encoding, "do-" is some transformation. -- These are typically not reversible, some could be recoverable.@@ -183,7 +184,7 @@ instance HasA SizeLimit Config where has = sizeLimit --- | `helloTitle' is needed in following examples+-- | @helloTitle'@ is needed in following examples -- helloTitle :: Enc '["do-Title"] Config T.Text helloTitle = encodeAll . toEncoding exampleConf $ "hello wOrld"
+ src/Examples/TypedEncoding/SomeEnc.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE RankNTypes #-}++-- |+-- This module defines 'SomeEnc' - existentially quantified version of @Enc@+-- and basic combinators.+--+-- This construction is common to more dependently typed Haskell but is +-- isomorphic to 'Data.TypedEncoding.Common.Types.CheckedEnc.CheckedEnc'. +--+-- Post v0.4 /typed-encoding/ supports @CheckedEnc@ while @SomeEnc@ remains as+-- as example.+--+-- (Moved from @Data.TypedEncoding.Common.Types.SomeEnc@ in previous versions)+--+-- @since 0.5.0.0++module Examples.TypedEncoding.SomeEnc where++import Data.TypedEncoding.Common.Types.Enc+import Data.TypedEncoding.Common.Class.Common+import Data.TypedEncoding.Common.Types.CheckedEnc+import Examples.TypedEncoding.SomeEnc.SomeAnnotation++-- $setup+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes+-- >>> import qualified Data.Text as T+-- >>> import Data.TypedEncoding.Combinators.Unsafe++++-- | Existentially quantified quantified @Enc@+-- effectively isomorphic to 'CheckedEnc'+--+-- @since 0.2.0.0+data SomeEnc conf str where+ MkSomeEnc :: SymbolList xs => Enc xs conf str -> SomeEnc conf str++-- |+-- @since 0.2.0.0 +withSomeEnc :: SomeEnc conf str -> (forall xs . SymbolList xs => Enc xs conf str -> r) -> r+withSomeEnc (MkSomeEnc enc) f = f enc++-- |+-- @since 0.2.0.0 +toSome :: SymbolList xs => Enc xs conf str -> SomeEnc conf str+toSome = MkSomeEnc++-- | +-- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text+-- >>> someToChecked . MkSomeEnc $ enctest+-- UnsafeMkCheckedEnc ["TEST"] () "hello"+-- +-- @since 0.2.0.0 +someToChecked :: SomeEnc conf str -> CheckedEnc conf str+someToChecked se = withSomeEnc se toCheckedEnc++-- | +-- >>> let tst = unsafeCheckedEnc ["TEST"] () "test"+-- >>> displ $ checkedToSome tst+-- "Some (Enc '[TEST] () (String test))"+-- +-- @since 0.2.0.0 s+checkedToSome :: CheckedEnc conf str -> SomeEnc conf str+checkedToSome (UnsafeMkCheckedEnc xs c s) = withSomeAnnotation (someAnnValue xs) (\p -> MkSomeEnc (UnsafeMkEnc p c s))+++-- |+-- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text+-- >>> displ $ MkSomeEnc enctest+-- "Some (Enc '[TEST] () (Text hello))"+instance (Show c, Displ str) => Displ (SomeEnc c str) where+ displ (MkSomeEnc en) = + "Some (" ++ displ en ++ ")"
+ src/Examples/TypedEncoding/SomeEnc/SomeAnnotation.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE RankNTypes #-}++-- | Internally used existential type for tracking of annotations+--+-- This module is re-exported in "Data.TypedEncoding" and it is best not to import it directly.++module Examples.TypedEncoding.SomeEnc.SomeAnnotation where++import Data.TypedEncoding.Common.Types.Common+import Data.TypedEncoding.Common.Class.Common+import Data.TypedEncoding.Common.Util.TypeLits (withSomeSymbol, proxyCons)+import Data.Proxy+import GHC.TypeLits++-- |+-- @since 0.2.0.0+data SomeAnnotation where+ MkSomeAnnotation :: SymbolList xs => Proxy xs -> SomeAnnotation++-- |+-- @since 0.2.0.0+withSomeAnnotation :: SomeAnnotation -> (forall xs . SymbolList xs => Proxy xs -> r) -> r+withSomeAnnotation (MkSomeAnnotation p) fn = fn p+++-- | folds over SomeSymbol list +-- @since 0.2.0.0+someAnnValue :: [EncAnn] -> SomeAnnotation+someAnnValue xs = + foldr (fn . someSymbolVal) (MkSomeAnnotation (Proxy :: Proxy '[])) xs+ where + somesymbs = map someSymbolVal xs+ fn ss (MkSomeAnnotation pxs) = withSomeSymbol ss (\px -> MkSomeAnnotation (px `proxyCons` pxs)) ++
src/Examples/TypedEncoding/ToEncString.hs view
@@ -30,7 +30,7 @@ -- Current version of typed-encoding does not have dependencies on such types. -- -- These examples use 'CheckedEnc' when untyped version of 'Enc' is needed.--- Alternatively, an existentially quantified 'SomeEnc' type could have been used.+-- Alternatively, an existentially quantified 'Examples.TypedEncoding.SomeEnc' type could have been used. -- Both are isomorphic. module Examples.TypedEncoding.ToEncString where @@ -86,10 +86,10 @@ -- UnsafeMkEnc Proxy () "128.1.1.10" -- -- Implementation is a classic map reduce where reduce is done with help of--- 'EnT.foldEncStr'+-- 'EnT.foldEnc' -- -- >>> let fn a b = if b == "" then a else a <> "." <> b--- >>> let reduce = EnT.foldEncStr @'["r-IPv4"] @'["r-Word8-decimal"] () fn+-- >>> let reduce = EnT.foldEnc @'["r-IPv4"] @'["r-Word8-decimal"] () fn "" -- >>> displ . reduce . fmap toEncString $ tstIp -- "Enc '[r-IPv4] () (String 128.1.1.10)" --@@ -112,7 +112,7 @@ map = fmap toEncString reduce :: IpV4F (Enc '["r-Word8-decimal"] () T.Text) -> Enc '["r-IPv4"] () T.Text - reduce = EnT.foldEncStr () (\a b-> if b == "" then a else a <> "." <> b) + reduce = EnT.foldEnc () (\a b-> if b == "" then a else a <> "." <> b) "" -- | --
+ src/Examples/TypedEncoding/Util.hs view
@@ -0,0 +1,20 @@++{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}++-- | Some helper definitions used in /Examples/+module Examples.TypedEncoding.Util where+++-- | Polymorphic data payloads used to encode/decode+--+-- This class is intended for example use only and will be moved to Example modules.+-- +-- Use your favorite polymorphic records / ad-hock product polymorphism library.+--+-- @since 0.1.0.0+class HasA a c where+ has :: c -> a++instance HasA () c where+ has = const ()
typed-encoding.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: d82580e7a0363bd4ef2af6a3a7d41d10d0cb724efc6066bc066c3d91ded51810+-- hash: 14b481e19f8b924154bf83e2d8d55492f1f8259385026d9dc0c745a2924621fa name: typed-encoding-version: 0.4.2.0+version: 0.5.0.0 synopsis: Type safe string transformations description: See README.md in the project github repository. category: Data, Text@@ -39,11 +39,11 @@ Data.TypedEncoding.Combinators.Unsafe Data.TypedEncoding.Combinators.Validate Data.TypedEncoding.Common.Class+ Data.TypedEncoding.Common.Class.Common Data.TypedEncoding.Common.Class.Decode Data.TypedEncoding.Common.Class.Encode Data.TypedEncoding.Common.Class.IsStringR Data.TypedEncoding.Common.Class.Superset- Data.TypedEncoding.Common.Class.Util Data.TypedEncoding.Common.Class.Util.StringConstraints Data.TypedEncoding.Common.Class.Validate Data.TypedEncoding.Common.Types@@ -52,8 +52,6 @@ Data.TypedEncoding.Common.Types.Decoding Data.TypedEncoding.Common.Types.Enc Data.TypedEncoding.Common.Types.Exceptions- Data.TypedEncoding.Common.Types.SomeAnnotation- Data.TypedEncoding.Common.Types.SomeEnc Data.TypedEncoding.Common.Types.UncheckedEnc Data.TypedEncoding.Common.Types.Unsafe Data.TypedEncoding.Common.Types.Validation@@ -65,10 +63,9 @@ Data.TypedEncoding.Conv.Text.Encoding Data.TypedEncoding.Conv.Text.Lazy Data.TypedEncoding.Conv.Text.Lazy.Encoding- Data.TypedEncoding.Instances.Do.Sample Data.TypedEncoding.Instances.Enc.Base64+ Data.TypedEncoding.Instances.Enc.Warn.Base64 Data.TypedEncoding.Instances.Restriction.ASCII- Data.TypedEncoding.Instances.Restriction.Bool Data.TypedEncoding.Instances.Restriction.BoundedAlphaNums Data.TypedEncoding.Instances.Restriction.ByteRep Data.TypedEncoding.Instances.Restriction.CHAR8@@ -77,7 +74,6 @@ Data.TypedEncoding.Instances.Restriction.UTF8 Data.TypedEncoding.Instances.Support Data.TypedEncoding.Instances.Support.Bool- Data.TypedEncoding.Instances.Support.Common Data.TypedEncoding.Instances.Support.Decode Data.TypedEncoding.Instances.Support.Encode Data.TypedEncoding.Instances.Support.Helpers@@ -87,10 +83,14 @@ Data.TypedEncoding.Unsafe Examples.TypedEncoding Examples.TypedEncoding.Conversions- Examples.TypedEncoding.DiySignEncoding+ Examples.TypedEncoding.Instances.DiySignEncoding+ Examples.TypedEncoding.Instances.Do.Sample Examples.TypedEncoding.Overview+ Examples.TypedEncoding.SomeEnc+ Examples.TypedEncoding.SomeEnc.SomeAnnotation Examples.TypedEncoding.ToEncString Examples.TypedEncoding.Unsafe+ Examples.TypedEncoding.Util other-modules: Paths_typed_encoding hs-source-dirs: