typed-encoding- Type safe string transformations

Safe HaskellSafe




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 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 Unsafe.



>>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds
>>> import Test.QuickCheck.Instances.Text()

encodeSign :: Text -> Text Source #

encoding function, typically should be module private

decodeSign :: Text -> Either String Text Source #

dual purpose decoding and recovery function.

This typically should be module private.

>>> decodeSign "3:abc"
Right "abc"
>>> decodeSign "4:abc"
Left "Corrupted Signature"

helloSigned :: Enc '["my-sign"] () Text Source #

Encoded hello world example.

>>> helloSigned
UnsafeMkEnc Proxy () "11:Hello World"
>>> fromEncoding . decodeAll $ helloSigned
"Hello World"

propEncDec :: Text -> Bool Source #

property checks that Text values are expected to decode without error after encoding.

\t -> propEncDec

hacker :: Either RecreateEx (Enc '["my-sign"] () Text) Source #

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")

decMySign :: (UnexpectedDecodeErr f, Applicative f) => Decoding f "my-sign" "my-sign" c Text Source #

Orphan instances

Applicative f => Encode f "my-sign" "my-sign" c Text Source #

Because encoding function is pure we can create instance of Encode that is polymorphic in effect f.

This is done using implTranP combinator.

Instance details


encoding :: Encoding f "my-sign" "my-sign" c Text Source #

(RecreateErr f, Applicative f) => Validate f "my-sign" "my-sign" c Text Source #

Recreation allows effectful f to check for tampering with data.

Implementation simply uses validFromDec combinator on the recovery function.

Instance details


validation :: Validation f "my-sign" "my-sign" c Text Source #

(UnexpectedDecodeErr f, Applicative f) => Decode f "my-sign" "my-sign" c Text Source #

Decoding allows effectful f to allow for troubleshooting and unsafe payload changes.

Implementation simply uses 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 details


decoding :: Decoding f "my-sign" "my-sign" c Text Source #