typed-encoding-0.1.0.0: Type safe string transformations

Safe HaskellSafe
LanguageHaskell2010

Examples.TypedEncoding.Overview

Contents

Description

type-encoding overview examples.

This library is concerned with 3 main operations done on strings: encoding, decoding, and recovery. Examples in this module cover all of these base cases.

This module uses encoding instances found in

Synopsis

Documentation

>>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds

This module contains some ghci friendly values to play with.

Each value is documented in a doctest style by including an equivalent ghci ready expression. These documents generate a test suite for this library as well.

Basics

helloB64 :: Enc '["enc-B64"] () ByteString Source #

"Hello World" encoded as Base64

>>> helloB64
MkEnc Proxy () "SGVsbG8gV29ybGQ="
>>> displ helloB64
"MkEnc '[enc-B64] () (ByteString SGVsbG8gV29ybGQ=)"
>>> encodeAll . toEncoding () $ "Hello World" :: Enc '["enc-B64"] () B.ByteString
MkEnc Proxy () "SGVsbG8gV29ybGQ="

helloB64Decoded :: ByteString Source #

Previous text decoded from Base64

>>> fromEncoding . decodeAll $ helloB64
"Hello World"

helloB64Recovered :: Either RecreateEx (Enc '["enc-B64"] () ByteString) Source #

recreateFAll allows for recovering data at program boundaries (for example, when parsing JSON input). It makes sure that the content satisfies specified encodings.

>>> recreateFAll . toEncoding () $ "SGVsbG8gV29ybGQ=" :: Either RecreateEx (Enc '["enc-B64"] () B.ByteString)
Right (MkEnc Proxy () "SGVsbG8gV29ybGQ=")
>>> recreateFAll . toEncoding () $ "SGVsbG8gV29ybGQ" :: Either RecreateEx (Enc '["enc-B64"] () B.ByteString)
Left (RecreateEx "enc-B64" ("invalid padding"))

helloB64B64 :: Enc '["enc-B64", "enc-B64"] () ByteString Source #

"Hello World" double-Base64 encoded. Notice the same code used as in single encoding, the game is played at type level.

>>> encodeAll . toEncoding () $ "Hello World" :: Enc '["enc-B64","enc-B64"] () B.ByteString
MkEnc Proxy () "U0dWc2JHOGdWMjl5YkdRPQ=="
>>> displ helloB64B64
"MkEnc '[enc-B64,enc-B64] () (ByteString U0dWc2JHOGdWMjl5YkdRPQ==)"

helloB64B64PartDecode :: Enc '["enc-B64"] () ByteString Source #

Double Base64 encoded "Hello World" with one layer of encoding removed

>>> decodePart (Proxy :: Proxy '["enc-B64"]) $ helloB64B64 :: Enc '["enc-B64"] () B.ByteString
MkEnc Proxy () "SGVsbG8gV29ybGQ="
>>> helloB64B64PartDecode == helloB64
True

helloB64B64Decoded :: ByteString Source #

helloB64B64 all the way to ByteString

Notice a similar polymorphism in decoding.

>>> fromEncoding . decodeAll $ helloB64B64 :: B.ByteString
"Hello World"

We can also decode all the parts:

>>> fromEncoding . decodePart (Proxy :: Proxy '["enc-B64","enc-B64"]) $ helloB64B64
"Hello World"

helloB64B64RecoveredErr :: Either RecreateEx (Enc '["enc-B64", "enc-B64"] () ByteString) Source #

what happens when we try to recover encoded once text to Enc '["enc-B64", "enc-B64"].

Again, notice the same expression is used as in previous recovery.

>>> recreateFAll . toEncoding () $ "SGVsbG8gV29ybGQ=" :: Either RecreateEx (Enc '["enc-B64", "enc-B64"] () B.ByteString)
Left (RecreateEx "enc-B64" ("invalid padding"))

"do-" Encodings

helloUPP :: Enc '["do-UPPER"] () Text Source #

"do-UPPER" (from 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.

The same code is used as in "enc-" examples to encode (now transform).

>>> encodeAll . toEncoding () $ "Hello World" :: Enc '["do-UPPER"] () T.Text
MkEnc Proxy () "HELLO WORLD"

helloTitleRev :: Enc '["do-reverse", "do-Title"] () Text Source #

Sample compound transformation

>>> encodeAll . toEncoding () $ "HeLLo world" :: Enc '["do-reverse", "do-Title"] () T.Text
MkEnc Proxy () "dlroW olleH" 

Configuration

data Config Source #

Example configuration

Constructors

Config 

Fields

Instances
Show Config Source # 
Instance details

Defined in Examples.TypedEncoding.Overview

HasA Config SizeLimit Source # 
Instance details

Defined in Examples.TypedEncoding.Overview

helloTitle :: Enc '["do-Title"] Config Text Source #

helloTitle is needed in following examples

helloRevLimit :: Enc '["do-size-limit", "do-reverse", "do-Title"] Config Text Source #

Configuration can be used to impact the encoding process.

So far we had used () as configuration of all encodings. But since both "do-reverse", "do-Title" are polymorphic in configuration we can also do this:

>>> encodeAll . toEncoding exampleConf $ "HeLLo world" :: Enc '["do-reverse", "do-Title"] Config T.Text
MkEnc Proxy (Config {sizeLimit = SizeLimit {unSizeLimit = 8}}) "dlroW olleH"
>>> encodeAll . toEncoding exampleConf $ "HeLlo world" :: Enc '["do-size-limit", "do-reverse", "do-Title"] Config T.Text
MkEnc Proxy (Config {sizeLimit = SizeLimit {unSizeLimit = 8}}) "dlroW ol"

Instead, encode previously defined helloTitle by reversing it and adding size limit

>>> encodePart (Proxy :: Proxy '["do-size-limit", "do-reverse"]) helloTitle :: Enc '["do-size-limit", "do-reverse", "do-Title"] Config T.Text
MkEnc Proxy (Config {sizeLimit = SizeLimit {unSizeLimit = 8}}) "dlroW ol"

helloLimitB64 :: Enc '["enc-B64", "do-size-limit"] Config ByteString Source #

helloRevLimitParDec :: Enc '["do-size-limit"] Config ByteString Source #

... and we unwrap the B64 part only

>>> decodePart (Proxy :: Proxy '["enc-B64"]) $ helloLimitB64
MkEnc Proxy (Config {sizeLimit = SizeLimit {unSizeLimit = 8}}) "HeLlo wo"

"r-" encodings section

helloAscii :: Either EncodeEx (Enc '["r-ASCII"] () ByteString) Source #

ASCII char set ByteStrings are sequences of Bytes (Word8). The type is very permissive, it may contain binary data such as jpeg picture.

"r-ASCII" encoding acts as partial identity function it does not change any bytes in bytestring but it fails if a byte is outside of ASCII range (in Either monad).

Note naming thing: "r-" is partial identity ("r-" is from restriction).

>>> encodeFAll . toEncoding () $ "HeLlo world" :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString)
Right (MkEnc Proxy () "HeLlo world")

helloAsciiB64 :: Either EncodeEx (Enc '["enc-B64", "r-ASCII"] () ByteString) Source #

Arguably the type we used for helloB64 was too permissive. a better version is here:

>>> encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["enc-B64", "r-ASCII"] () B.ByteString)
Right (MkEnc Proxy () "SGVsbG8gV29ybGQ=") 

helloAsciiB64PartDec :: Either EncodeEx (Enc '["r-ASCII"] () ByteString) Source #

>>> decodePart (Proxy :: Proxy '["enc-B64"]) <$> helloAsciiB64
Right (MkEnc Proxy () "Hello World")