{-# LANGUAGE MultiParamTypeClasses #-}
-- {-# LANGUAGE PolyKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PartialTypeSignatures #-}

{-# OPTIONS_GHC -Wno-partial-type-signatures #-}

-- |
-- This module shows use of 'ToEncString' and 'FromEncString'
-- and demonstrates /composite/ encoding.
--
-- @Show@ and @Read@ classes use a very permissive String type. This often results in 
-- read errors. type-encoding approach provides type safety over decoding process.
--
-- This module includes a simplified email example. This is a non-homogeneous case, 
-- email parts do not have the same encoding. 
--
-- Examples here could be made more type safe with use of dependently typed
-- concepts like @Vect@, @HList@ or variant equivalents of these types.
--
-- 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 'Examples.TypedEncoding.SomeEnc' type could have been used.
-- Both are isomorphic.  
module Examples.TypedEncoding.ToEncString where

import           Data.TypedEncoding
import qualified Data.TypedEncoding.Instances.Support as EnT
import           Data.TypedEncoding.Instances.Restriction.Misc ()
import           Data.TypedEncoding.Instances.Enc.Base64 ()
import           Data.TypedEncoding.Instances.Restriction.ASCII ()
import           Data.TypedEncoding.Instances.Restriction.UTF8 ()

import           Data.Word
import           Data.Functor.Identity
import qualified Data.Text as T
import qualified Data.ByteString as B
import           Control.Applicative -- ((<|>))
import           Data.Maybe




-- $setup
-- >>> :set -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XFlexibleInstances -XTypeApplications -XOverloadedStrings
-- >>> import qualified Data.List as L


-- * IpV4 example

type IpV4 = IpV4F Word8

-- | 
-- In this example all data fields have the same type. 
-- This simplifies encoding work as all fields will be encoded the same way.
-- We use IP address since all fields are single byte size.
data IpV4F a = IpV4F {
     IpV4F a -> a
oct1 :: a
     , IpV4F a -> a
oct2 :: a
     , IpV4F a -> a
oct3 :: a
     , IpV4F a -> a
oct4 :: a
   } deriving (Int -> IpV4F a -> ShowS
[IpV4F a] -> ShowS
IpV4F a -> String
(Int -> IpV4F a -> ShowS)
-> (IpV4F a -> String) -> ([IpV4F a] -> ShowS) -> Show (IpV4F a)
forall a. Show a => Int -> IpV4F a -> ShowS
forall a. Show a => [IpV4F a] -> ShowS
forall a. Show a => IpV4F a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IpV4F a] -> ShowS
$cshowList :: forall a. Show a => [IpV4F a] -> ShowS
show :: IpV4F a -> String
$cshow :: forall a. Show a => IpV4F a -> String
showsPrec :: Int -> IpV4F a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> IpV4F a -> ShowS
Show, a -> IpV4F b -> IpV4F a
(a -> b) -> IpV4F a -> IpV4F b
(forall a b. (a -> b) -> IpV4F a -> IpV4F b)
-> (forall a b. a -> IpV4F b -> IpV4F a) -> Functor IpV4F
forall a b. a -> IpV4F b -> IpV4F a
forall a b. (a -> b) -> IpV4F a -> IpV4F b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> IpV4F b -> IpV4F a
$c<$ :: forall a b. a -> IpV4F b -> IpV4F a
fmap :: (a -> b) -> IpV4F a -> IpV4F b
$cfmap :: forall a b. (a -> b) -> IpV4F a -> IpV4F b
Functor, IpV4F a -> Bool
(a -> m) -> IpV4F a -> m
(a -> b -> b) -> b -> IpV4F a -> b
(forall m. Monoid m => IpV4F m -> m)
-> (forall m a. Monoid m => (a -> m) -> IpV4F a -> m)
-> (forall m a. Monoid m => (a -> m) -> IpV4F a -> m)
-> (forall a b. (a -> b -> b) -> b -> IpV4F a -> b)
-> (forall a b. (a -> b -> b) -> b -> IpV4F a -> b)
-> (forall b a. (b -> a -> b) -> b -> IpV4F a -> b)
-> (forall b a. (b -> a -> b) -> b -> IpV4F a -> b)
-> (forall a. (a -> a -> a) -> IpV4F a -> a)
-> (forall a. (a -> a -> a) -> IpV4F a -> a)
-> (forall a. IpV4F a -> [a])
-> (forall a. IpV4F a -> Bool)
-> (forall a. IpV4F a -> Int)
-> (forall a. Eq a => a -> IpV4F a -> Bool)
-> (forall a. Ord a => IpV4F a -> a)
-> (forall a. Ord a => IpV4F a -> a)
-> (forall a. Num a => IpV4F a -> a)
-> (forall a. Num a => IpV4F a -> a)
-> Foldable IpV4F
forall a. Eq a => a -> IpV4F a -> Bool
forall a. Num a => IpV4F a -> a
forall a. Ord a => IpV4F a -> a
forall m. Monoid m => IpV4F m -> m
forall a. IpV4F a -> Bool
forall a. IpV4F a -> Int
forall a. IpV4F a -> [a]
forall a. (a -> a -> a) -> IpV4F a -> a
forall m a. Monoid m => (a -> m) -> IpV4F a -> m
forall b a. (b -> a -> b) -> b -> IpV4F a -> b
forall a b. (a -> b -> b) -> b -> IpV4F a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: IpV4F a -> a
$cproduct :: forall a. Num a => IpV4F a -> a
sum :: IpV4F a -> a
$csum :: forall a. Num a => IpV4F a -> a
minimum :: IpV4F a -> a
$cminimum :: forall a. Ord a => IpV4F a -> a
maximum :: IpV4F a -> a
$cmaximum :: forall a. Ord a => IpV4F a -> a
elem :: a -> IpV4F a -> Bool
$celem :: forall a. Eq a => a -> IpV4F a -> Bool
length :: IpV4F a -> Int
$clength :: forall a. IpV4F a -> Int
null :: IpV4F a -> Bool
$cnull :: forall a. IpV4F a -> Bool
toList :: IpV4F a -> [a]
$ctoList :: forall a. IpV4F a -> [a]
foldl1 :: (a -> a -> a) -> IpV4F a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> IpV4F a -> a
foldr1 :: (a -> a -> a) -> IpV4F a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> IpV4F a -> a
foldl' :: (b -> a -> b) -> b -> IpV4F a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> IpV4F a -> b
foldl :: (b -> a -> b) -> b -> IpV4F a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> IpV4F a -> b
foldr' :: (a -> b -> b) -> b -> IpV4F a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> IpV4F a -> b
foldr :: (a -> b -> b) -> b -> IpV4F a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> IpV4F a -> b
foldMap' :: (a -> m) -> IpV4F a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> IpV4F a -> m
foldMap :: (a -> m) -> IpV4F a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> IpV4F a -> m
fold :: IpV4F m -> m
$cfold :: forall m. Monoid m => IpV4F m -> m
Foldable)

tstIp :: IpV4
tstIp :: IpV4
tstIp = Word8 -> Word8 -> Word8 -> Word8 -> IpV4
forall a. a -> a -> a -> a -> IpV4F a
IpV4F Word8
128 Word8
1 Word8
1 Word8
10



-- |
-- In this example @toEncString@ converts our example 'IpV4' type to @Enc '["r-IPv4"] Text@.
--
-- This is done with help of existing @"r-Word8-decimal"@ annotation defined
-- in "Data.TypedEncoding.Instances.Restriction.Misc"
--
-- >>> toEncString @"r-IPv4" @IpV4 @T.Text tstIp
-- UnsafeMkEnc Proxy () "128.1.1.10"
--
-- Implementation is a classic map reduce where reduce is done with help of
-- 'EnT.foldEnc'
--
-- >>> let fn a b = if b == "" then a else a <> "." <> b
-- >>> let reduce = EnT.foldEnc @'["r-IPv4"] @'["r-Word8-decimal"] () fn ""
-- >>>  displ . reduce . fmap toEncString $ tstIp
-- "Enc '[r-IPv4] () (String 128.1.1.10)"
--
-- Note lack of type safety here, the same code would work just fine if we added
-- 5th field to 'IpV4F' constructor.  
--
-- Using something like a dependently typed
--
-- @
-- Vect 4 (Enc '["r-Word8-decimal"] () T.Text)
-- @ 
-- 
-- would have improved this situation.
-- @HList@ could be used for record types with heterogeneous fields.
--
-- Currently, 'type-encoding' library does not have these types in scope.  
instance ToEncString Identity "r-IPv4" "r-IPv4" IpV4 T.Text where
    toEncF :: IpV4
-> Identity
     (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text)
toEncF = Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> Identity
     (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text)
forall a. a -> Identity a
Identity (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
 -> Identity
      (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text))
-> (IpV4
    -> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text)
-> IpV4
-> Identity
     (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IpV4F
  (Enc
     @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
reduce (IpV4F
   (Enc
      @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
 -> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text)
-> (IpV4
    -> IpV4F
         (Enc
            @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
-> IpV4
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IpV4
-> IpV4F
     (Enc
        @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
map
      where map :: IpV4F Word8 -> IpV4F (Enc '["r-Word8-decimal"] () T.Text) 
            map :: IpV4
-> IpV4F
     (Enc
        @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
map = (Word8
 -> Enc
      @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
-> IpV4
-> IpV4F
     (Enc
        @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word8
-> Enc
     @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text
forall (nm :: Symbol) a str.
ToEncString Identity nm nm a str =>
a -> Enc @[Symbol] ((':) @Symbol nm ('[] @Symbol)) () str
toEncString

            reduce :: IpV4F (Enc '["r-Word8-decimal"] () T.Text) -> Enc '["r-IPv4"] () T.Text 
            reduce :: IpV4F
  (Enc
     @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
reduce = ()
-> (Text -> Text -> Text)
-> Text
-> IpV4F
     (Enc
        @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
forall (xs2 :: [Symbol]) (xs1 :: [Symbol]) (f :: * -> *) c s1 s2.
(Foldable f, Functor f) =>
c
-> (s1 -> s2 -> s2)
-> s2
-> f (Enc @[Symbol] xs1 c s1)
-> Enc @[Symbol] xs2 c s2
EnT.foldEnc () (\Text
a Text
b-> if Text
b Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"" then Text
a else Text
a Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
b) Text
""

-- |
--
-- >>> let enc = toEncString @"r-IPv4" @IpV4 @T.Text tstIp
-- >>> fromEncString @"r-IPv4" @IpV4 enc
-- IpV4F {oct1 = 128, oct2 = 1, oct3 = 1, oct4 = 10}
--
-- To get 'IpV4' out of the string we need to reverse previous @reduce@.
-- This is currently done using helper 'EnT.splitPayload' combinator. 
--
-- >>> EnT.splitPayload @'["r-Word8-decimal"] (T.splitOn $ T.pack ".") $ enc 
-- [UnsafeMkEnc Proxy () "128",UnsafeMkEnc Proxy () "1",UnsafeMkEnc Proxy () "1",UnsafeMkEnc Proxy () "10"]
-- 
-- The conversion of a list to IpV4F needs handle errors but these errors 
-- are considered unexpected.
--
-- Note, again, the error condition exposed by this implementation could have been avoided
-- if 'EnT.splitPayload' returned fixed size @Vect 4@.
instance (UnexpectedDecodeErr f, Applicative f) => FromEncString f "r-IPv4" "r-IPv4" IpV4 T.Text where   
    fromEncF :: Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> f IpV4
fromEncF = (IpV4F
   (Enc
      @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
 -> IpV4)
-> f (IpV4F
        (Enc
           @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
-> f IpV4
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IpV4F
  (Enc
     @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
-> IpV4
map (f (IpV4F
      (Enc
         @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
 -> f IpV4)
-> (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
    -> f (IpV4F
            (Enc
               @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)))
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> f IpV4
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> f (IpV4F
        (Enc
           @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
unreduce
      where unreduce :: Enc '["r-IPv4"] () T.Text -> f (IpV4F (Enc '["r-Word8-decimal"] () T.Text))
            unreduce :: Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> f (IpV4F
        (Enc
           @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
unreduce = forall (x :: Symbol) (f :: * -> *) err a.
(KnownSymbol x, UnexpectedDecodeErr @* f, Applicative f,
 Show err) =>
Either err a -> f a
forall (f :: * -> *) err a.
(KnownSymbol "r-IPv4", UnexpectedDecodeErr @* f, Applicative f,
 Show err) =>
Either err a -> f a
asUnexpected @"r-IPv4" (Either
   String
   (IpV4F
      (Enc
         @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
 -> f (IpV4F
         (Enc
            @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)))
-> (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
    -> Either
         String
         (IpV4F
            (Enc
               @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)))
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> f (IpV4F
        (Enc
           @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Enc
   @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text]
-> Either
     String
     (IpV4F
        (Enc
           @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
forall a. Show a => [a] -> Either String (IpV4F a)
recover ([Enc
    @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text]
 -> Either
      String
      (IpV4F
         (Enc
            @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)))
-> (Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
    -> [Enc
          @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text])
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> Either
     String
     (IpV4F
        (Enc
           @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> [Text])
-> Enc @[Symbol] ((':) @Symbol "r-IPv4" ('[] @Symbol)) () Text
-> [Enc
      @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text]
forall (xs2 :: [Symbol]) (xs1 :: [Symbol]) c s1 s2.
(s1 -> [s2]) -> Enc @[Symbol] xs1 c s1 -> [Enc @[Symbol] xs2 c s2]
EnT.splitPayload @'["r-Word8-decimal"] (Text -> Text -> [Text]
T.splitOn Text
".")
            
            map :: IpV4F (Enc '["r-Word8-decimal"] () T.Text) -> IpV4F Word8 
            map :: IpV4F
  (Enc
     @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
-> IpV4
map = (Enc
   @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text
 -> Word8)
-> IpV4F
     (Enc
        @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text)
-> IpV4
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Enc
  @[Symbol] ((':) @Symbol "r-Word8-decimal" ('[] @Symbol)) () Text
-> Word8
forall (nm :: Symbol) a str.
FromEncString @* Identity nm nm a str =>
Enc @[Symbol] ((':) @Symbol nm ('[] @Symbol)) () str -> a
fromEncString

            recover ::  Show a => [a] -> Either String (IpV4F a)
            recover :: [a] -> Either String (IpV4F a)
recover [a
o1,a
o2,a
o3,a
o4] = IpV4F a -> Either String (IpV4F a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (IpV4F a -> Either String (IpV4F a))
-> IpV4F a -> Either String (IpV4F a)
forall a b. (a -> b) -> a -> b
$ a -> a -> a -> a -> IpV4F a
forall a. a -> a -> a -> a -> IpV4F a
IpV4F a
o1 a
o2 a
o3 a
o4
            recover [a]
x = String -> Either String (IpV4F a)
forall a b. a -> Either a b
Left (String -> Either String (IpV4F a))
-> String -> Either String (IpV4F a)
forall a b. (a -> b) -> a -> b
$ String
"Invalid Content" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [a] -> String
forall a. Show a => a -> String
show [a]
x




-- * Simplified email example


-- | Simplified Part header  
type PartHeader = [String]

-- | Simplified Email header  
type EmailHeader = String

-- | This section shows a type safe processing of emails.
--
-- 'SimplifiedEmailF' is an over-simplified email type, it has parts that can be either 
-- 
-- * binary and have to be Base 64 encoded or 
-- * are text that have either UTF8 or ASCII character set 
--
-- The text parts can be optionally can be Base 64 encoded but do not have to be.
--
-- For simplicity, the layout of simplified headers is assumed the same as encoding annotations in this library.
data SimplifiedEmailF a = SimplifiedEmailF {
          SimplifiedEmailF a -> String
emailHeader :: EmailHeader
          , SimplifiedEmailF a -> [a]
parts :: [a]
      } deriving (Int -> SimplifiedEmailF a -> ShowS
[SimplifiedEmailF a] -> ShowS
SimplifiedEmailF a -> String
(Int -> SimplifiedEmailF a -> ShowS)
-> (SimplifiedEmailF a -> String)
-> ([SimplifiedEmailF a] -> ShowS)
-> Show (SimplifiedEmailF a)
forall a. Show a => Int -> SimplifiedEmailF a -> ShowS
forall a. Show a => [SimplifiedEmailF a] -> ShowS
forall a. Show a => SimplifiedEmailF a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SimplifiedEmailF a] -> ShowS
$cshowList :: forall a. Show a => [SimplifiedEmailF a] -> ShowS
show :: SimplifiedEmailF a -> String
$cshow :: forall a. Show a => SimplifiedEmailF a -> String
showsPrec :: Int -> SimplifiedEmailF a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> SimplifiedEmailF a -> ShowS
Show, SimplifiedEmailF a -> SimplifiedEmailF a -> Bool
(SimplifiedEmailF a -> SimplifiedEmailF a -> Bool)
-> (SimplifiedEmailF a -> SimplifiedEmailF a -> Bool)
-> Eq (SimplifiedEmailF a)
forall a. Eq a => SimplifiedEmailF a -> SimplifiedEmailF a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SimplifiedEmailF a -> SimplifiedEmailF a -> Bool
$c/= :: forall a. Eq a => SimplifiedEmailF a -> SimplifiedEmailF a -> Bool
== :: SimplifiedEmailF a -> SimplifiedEmailF a -> Bool
$c== :: forall a. Eq a => SimplifiedEmailF a -> SimplifiedEmailF a -> Bool
Eq, a -> SimplifiedEmailF b -> SimplifiedEmailF a
(a -> b) -> SimplifiedEmailF a -> SimplifiedEmailF b
(forall a b. (a -> b) -> SimplifiedEmailF a -> SimplifiedEmailF b)
-> (forall a b. a -> SimplifiedEmailF b -> SimplifiedEmailF a)
-> Functor SimplifiedEmailF
forall a b. a -> SimplifiedEmailF b -> SimplifiedEmailF a
forall a b. (a -> b) -> SimplifiedEmailF a -> SimplifiedEmailF b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> SimplifiedEmailF b -> SimplifiedEmailF a
$c<$ :: forall a b. a -> SimplifiedEmailF b -> SimplifiedEmailF a
fmap :: (a -> b) -> SimplifiedEmailF a -> SimplifiedEmailF b
$cfmap :: forall a b. (a -> b) -> SimplifiedEmailF a -> SimplifiedEmailF b
Functor, SimplifiedEmailF a -> Bool
(a -> m) -> SimplifiedEmailF a -> m
(a -> b -> b) -> b -> SimplifiedEmailF a -> b
(forall m. Monoid m => SimplifiedEmailF m -> m)
-> (forall m a. Monoid m => (a -> m) -> SimplifiedEmailF a -> m)
-> (forall m a. Monoid m => (a -> m) -> SimplifiedEmailF a -> m)
-> (forall a b. (a -> b -> b) -> b -> SimplifiedEmailF a -> b)
-> (forall a b. (a -> b -> b) -> b -> SimplifiedEmailF a -> b)
-> (forall b a. (b -> a -> b) -> b -> SimplifiedEmailF a -> b)
-> (forall b a. (b -> a -> b) -> b -> SimplifiedEmailF a -> b)
-> (forall a. (a -> a -> a) -> SimplifiedEmailF a -> a)
-> (forall a. (a -> a -> a) -> SimplifiedEmailF a -> a)
-> (forall a. SimplifiedEmailF a -> [a])
-> (forall a. SimplifiedEmailF a -> Bool)
-> (forall a. SimplifiedEmailF a -> Int)
-> (forall a. Eq a => a -> SimplifiedEmailF a -> Bool)
-> (forall a. Ord a => SimplifiedEmailF a -> a)
-> (forall a. Ord a => SimplifiedEmailF a -> a)
-> (forall a. Num a => SimplifiedEmailF a -> a)
-> (forall a. Num a => SimplifiedEmailF a -> a)
-> Foldable SimplifiedEmailF
forall a. Eq a => a -> SimplifiedEmailF a -> Bool
forall a. Num a => SimplifiedEmailF a -> a
forall a. Ord a => SimplifiedEmailF a -> a
forall m. Monoid m => SimplifiedEmailF m -> m
forall a. SimplifiedEmailF a -> Bool
forall a. SimplifiedEmailF a -> Int
forall a. SimplifiedEmailF a -> [a]
forall a. (a -> a -> a) -> SimplifiedEmailF a -> a
forall m a. Monoid m => (a -> m) -> SimplifiedEmailF a -> m
forall b a. (b -> a -> b) -> b -> SimplifiedEmailF a -> b
forall a b. (a -> b -> b) -> b -> SimplifiedEmailF a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: SimplifiedEmailF a -> a
$cproduct :: forall a. Num a => SimplifiedEmailF a -> a
sum :: SimplifiedEmailF a -> a
$csum :: forall a. Num a => SimplifiedEmailF a -> a
minimum :: SimplifiedEmailF a -> a
$cminimum :: forall a. Ord a => SimplifiedEmailF a -> a
maximum :: SimplifiedEmailF a -> a
$cmaximum :: forall a. Ord a => SimplifiedEmailF a -> a
elem :: a -> SimplifiedEmailF a -> Bool
$celem :: forall a. Eq a => a -> SimplifiedEmailF a -> Bool
length :: SimplifiedEmailF a -> Int
$clength :: forall a. SimplifiedEmailF a -> Int
null :: SimplifiedEmailF a -> Bool
$cnull :: forall a. SimplifiedEmailF a -> Bool
toList :: SimplifiedEmailF a -> [a]
$ctoList :: forall a. SimplifiedEmailF a -> [a]
foldl1 :: (a -> a -> a) -> SimplifiedEmailF a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> SimplifiedEmailF a -> a
foldr1 :: (a -> a -> a) -> SimplifiedEmailF a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> SimplifiedEmailF a -> a
foldl' :: (b -> a -> b) -> b -> SimplifiedEmailF a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> SimplifiedEmailF a -> b
foldl :: (b -> a -> b) -> b -> SimplifiedEmailF a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> SimplifiedEmailF a -> b
foldr' :: (a -> b -> b) -> b -> SimplifiedEmailF a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> SimplifiedEmailF a -> b
foldr :: (a -> b -> b) -> b -> SimplifiedEmailF a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> SimplifiedEmailF a -> b
foldMap' :: (a -> m) -> SimplifiedEmailF a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> SimplifiedEmailF a -> m
foldMap :: (a -> m) -> SimplifiedEmailF a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> SimplifiedEmailF a -> m
fold :: SimplifiedEmailF m -> m
$cfold :: forall m. Monoid m => SimplifiedEmailF m -> m
Foldable, Functor SimplifiedEmailF
Foldable SimplifiedEmailF
Functor SimplifiedEmailF
-> Foldable SimplifiedEmailF
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> SimplifiedEmailF a -> f (SimplifiedEmailF b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    SimplifiedEmailF (f a) -> f (SimplifiedEmailF a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> SimplifiedEmailF a -> m (SimplifiedEmailF b))
-> (forall (m :: * -> *) a.
    Monad m =>
    SimplifiedEmailF (m a) -> m (SimplifiedEmailF a))
-> Traversable SimplifiedEmailF
(a -> f b) -> SimplifiedEmailF a -> f (SimplifiedEmailF b)
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a.
Monad m =>
SimplifiedEmailF (m a) -> m (SimplifiedEmailF a)
forall (f :: * -> *) a.
Applicative f =>
SimplifiedEmailF (f a) -> f (SimplifiedEmailF a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> SimplifiedEmailF a -> m (SimplifiedEmailF b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> SimplifiedEmailF a -> f (SimplifiedEmailF b)
sequence :: SimplifiedEmailF (m a) -> m (SimplifiedEmailF a)
$csequence :: forall (m :: * -> *) a.
Monad m =>
SimplifiedEmailF (m a) -> m (SimplifiedEmailF a)
mapM :: (a -> m b) -> SimplifiedEmailF a -> m (SimplifiedEmailF b)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> SimplifiedEmailF a -> m (SimplifiedEmailF b)
sequenceA :: SimplifiedEmailF (f a) -> f (SimplifiedEmailF a)
$csequenceA :: forall (f :: * -> *) a.
Applicative f =>
SimplifiedEmailF (f a) -> f (SimplifiedEmailF a)
traverse :: (a -> f b) -> SimplifiedEmailF a -> f (SimplifiedEmailF b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> SimplifiedEmailF a -> f (SimplifiedEmailF b)
$cp2Traversable :: Foldable SimplifiedEmailF
$cp1Traversable :: Functor SimplifiedEmailF
Traversable)

type SimplifiedEmail = SimplifiedEmailF (PartHeader, B.ByteString)

type SimplifiedEmailEncB = SimplifiedEmailF (CheckedEnc () B.ByteString)


-- | @tstEmail@ contains some simple data to play with
tstEmail :: SimplifiedEmail
tstEmail :: SimplifiedEmail
tstEmail = SimplifiedEmailF :: forall a. String -> [a] -> SimplifiedEmailF a
SimplifiedEmailF {
      emailHeader :: String
emailHeader = String
"Some Header"
      , parts :: [(PartHeader, ByteString)]
parts = [
        ([String
"enc-B64",String
"image"], ByteString
"U29tZSBBU0NJSSBUZXh0") 
        , ([String
"enc-B64",String
"r-ASCII"], ByteString
"U29tZSBBU0NJSSBUZXh0")
        , ([String
"enc-B64",String
"r-UTF8"], ByteString
"U29tZSBVVEY4IFRleHQ=") 
        , ([String
"r-ASCII"], ByteString
"Some ASCII plain text") 
         ]
  }

-- | 
-- This example encodes fields in 'SimplifiedEmailF' into an untyped version of @Enc@ which 
-- stores verified encoded data and encoding information is stored at the value level: 
-- @CheckedEnc () B.ByteString@.
-- 
-- Part of email are first converted to 'UncheckedEnc' (that stores encoding information at the value level as well).
-- 'UncheckedEnc'  that can easily represent parts of the email
--
-- >>> let part = parts tstEmail L.!! 2
-- >>> part
-- (["enc-B64","r-UTF8"],"U29tZSBVVEY4IFRleHQ=")
-- >>> let unchecked = toUncheckedEnc (fst part) () (snd part)
-- >>> unchecked 
-- MkUncheckedEnc ["enc-B64","r-UTF8"] () "U29tZSBVVEY4IFRleHQ="
--
-- We can play 'Alternative' ('<|>') game (we acually use @Maybe@) with final option being a 'RecreateEx' error:
--
-- >>> check @'["enc-B64","r-ASCII"] @(Either RecreateEx) $ unchecked
-- Nothing
-- >>> check @'["enc-B64","r-UTF8"] @(Either RecreateEx) $ unchecked
-- Just (Right (UnsafeMkEnc Proxy () "U29tZSBVVEY4IFRleHQ="))
--
-- Since the data is heterogeneous (each piece has a different encoding annotation), we need wrap the result in another plain ADT: 'CheckedEnc'.
-- 
-- 'CheckedEnc' is similar to 'UncheckedEnc' with the difference that the only (safe) way to get values of this type is
-- from properly encoded 'Enc' values. 
--
-- Using 'unsafeCheckedEnc' would break type safety here. 
-- 
-- It is important to handle all cases during encoding so decoding errors become impossible.
--
-- Again, use of dependently typed variant types that could enumerate all possible encodings
-- would made this code nicer.
recreateEncoding :: SimplifiedEmail -> Either RecreateEx SimplifiedEmailEncB
recreateEncoding :: SimplifiedEmail -> Either RecreateEx SimplifiedEmailEncB
recreateEncoding = ((PartHeader, ByteString)
 -> Either RecreateEx (CheckedEnc () ByteString))
-> SimplifiedEmail -> Either RecreateEx SimplifiedEmailEncB
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (PartHeader, ByteString)
-> Either RecreateEx (CheckedEnc () ByteString)
encodefn
  where 
        -- | simplified parse header assumes email has the same layout as encodings
        -- image is ingored, since [enc-B64] annotation on ByteString permits base 64
        -- encoded bytes
        parseHeader :: PartHeader -> [EncAnn]
        parseHeader :: PartHeader -> PartHeader
parseHeader [String
"enc-B64",String
"image"] = [String
"enc-B64"] 
        parseHeader PartHeader
x = PartHeader
x

        encodefn :: (PartHeader, B.ByteString) -> Either RecreateEx (CheckedEnc () B.ByteString)
        encodefn :: (PartHeader, ByteString)
-> Either RecreateEx (CheckedEnc () ByteString)
encodefn (PartHeader
parth, ByteString
body) = 
          (Maybe (Either RecreateEx (CheckedEnc () ByteString))
 -> Either RecreateEx (CheckedEnc () ByteString))
-> [ByteString
    -> Maybe (Either RecreateEx (CheckedEnc () ByteString))]
-> ByteString
-> Either RecreateEx (CheckedEnc () ByteString)
forall (f :: * -> *) b a.
Alternative f =>
(f b -> b) -> [a -> f b] -> a -> b
runAlternatives' (Either RecreateEx (CheckedEnc () ByteString)
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
-> Either RecreateEx (CheckedEnc () ByteString)
forall a. a -> Maybe a -> a
fromMaybe Either RecreateEx (CheckedEnc () ByteString)
forall b. Either RecreateEx b
def) [ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try1, ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try2, ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try3, ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try4, ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try5] ByteString
body
          where
              unchecked :: str -> UncheckedEnc () str
unchecked = PartHeader -> () -> str -> UncheckedEnc () str
forall c str. PartHeader -> c -> str -> UncheckedEnc c str
toUncheckedEnc (PartHeader -> PartHeader
parseHeader PartHeader
parth) () 
              try1 :: ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try1 = (Either
   RecreateEx
   (Enc
      @[Symbol]
      ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
      ()
      ByteString)
 -> Either RecreateEx (CheckedEnc () ByteString))
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol]
           ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
           ()
           ByteString))
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Enc
   @[Symbol]
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
   ()
   ByteString
 -> CheckedEnc () ByteString)
-> Either
     RecreateEx
     (Enc
        @[Symbol]
        ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
        ()
        ByteString)
-> Either RecreateEx (CheckedEnc () ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
  ()
  ByteString
-> CheckedEnc () ByteString
forall (xs :: [Symbol]) c str.
SymbolList xs =>
Enc @[Symbol] xs c str -> CheckedEnc c str
toCheckedEnc) (Maybe
   (Either
      RecreateEx
      (Enc
         @[Symbol]
         ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
         ()
         ByteString))
 -> Maybe (Either RecreateEx (CheckedEnc () ByteString)))
-> (ByteString
    -> Maybe
         (Either
            RecreateEx
            (Enc
               @[Symbol]
               ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
               ()
               ByteString)))
-> ByteString
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms nms c str, SymbolList nms) =>
UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
forall (f :: * -> *) c str.
(Monad f,
 ValidateAll
   f
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
   c
   str,
 SymbolList
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))) =>
UncheckedEnc c str
-> Maybe
     (f (Enc
           @[Symbol]
           ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
           c
           str))
check @'["enc-B64","r-UTF8"] (UncheckedEnc () ByteString
 -> Maybe
      (Either
         RecreateEx
         (Enc
            @[Symbol]
            ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
            ()
            ByteString)))
-> (ByteString -> UncheckedEnc () ByteString)
-> ByteString
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol]
           ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
           ()
           ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> UncheckedEnc () ByteString
forall str. str -> UncheckedEnc () str
unchecked
              try2 :: ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try2 = (Either
   RecreateEx
   (Enc
      @[Symbol]
      ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
      ()
      ByteString)
 -> Either RecreateEx (CheckedEnc () ByteString))
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol]
           ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
           ()
           ByteString))
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Enc
   @[Symbol]
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
   ()
   ByteString
 -> CheckedEnc () ByteString)
-> Either
     RecreateEx
     (Enc
        @[Symbol]
        ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
        ()
        ByteString)
-> Either RecreateEx (CheckedEnc () ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
  ()
  ByteString
-> CheckedEnc () ByteString
forall (xs :: [Symbol]) c str.
SymbolList xs =>
Enc @[Symbol] xs c str -> CheckedEnc c str
toCheckedEnc) (Maybe
   (Either
      RecreateEx
      (Enc
         @[Symbol]
         ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
         ()
         ByteString))
 -> Maybe (Either RecreateEx (CheckedEnc () ByteString)))
-> (ByteString
    -> Maybe
         (Either
            RecreateEx
            (Enc
               @[Symbol]
               ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
               ()
               ByteString)))
-> ByteString
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms nms c str, SymbolList nms) =>
UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
forall (f :: * -> *) c str.
(Monad f,
 ValidateAll
   f
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
   c
   str,
 SymbolList
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))) =>
UncheckedEnc c str
-> Maybe
     (f (Enc
           @[Symbol]
           ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
           c
           str))
check @'["enc-B64","r-ASCII"] (UncheckedEnc () ByteString
 -> Maybe
      (Either
         RecreateEx
         (Enc
            @[Symbol]
            ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
            ()
            ByteString)))
-> (ByteString -> UncheckedEnc () ByteString)
-> ByteString
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol]
           ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
           ()
           ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> UncheckedEnc () ByteString
forall str. str -> UncheckedEnc () str
unchecked
              try3 :: ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try3 = (Either
   RecreateEx
   (Enc
      @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString)
 -> Either RecreateEx (CheckedEnc () ByteString))
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString))
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Enc @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString
 -> CheckedEnc () ByteString)
-> Either
     RecreateEx
     (Enc
        @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString)
-> Either RecreateEx (CheckedEnc () ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Enc @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString
-> CheckedEnc () ByteString
forall (xs :: [Symbol]) c str.
SymbolList xs =>
Enc @[Symbol] xs c str -> CheckedEnc c str
toCheckedEnc) (Maybe
   (Either
      RecreateEx
      (Enc
         @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString))
 -> Maybe (Either RecreateEx (CheckedEnc () ByteString)))
-> (ByteString
    -> Maybe
         (Either
            RecreateEx
            (Enc
               @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString)))
-> ByteString
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms nms c str, SymbolList nms) =>
UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
forall (f :: * -> *) c str.
(Monad f,
 ValidateAll
   f
   ((':) @Symbol "r-ASCII" ('[] @Symbol))
   ((':) @Symbol "r-ASCII" ('[] @Symbol))
   c
   str,
 SymbolList ((':) @Symbol "r-ASCII" ('[] @Symbol))) =>
UncheckedEnc c str
-> Maybe
     (f (Enc @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) c str))
check @'["r-ASCII"] (UncheckedEnc () ByteString
 -> Maybe
      (Either
         RecreateEx
         (Enc
            @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString)))
-> (ByteString -> UncheckedEnc () ByteString)
-> ByteString
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> UncheckedEnc () ByteString
forall str. str -> UncheckedEnc () str
unchecked
              try4 :: ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try4 = (Either
   RecreateEx
   (Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString)
 -> Either RecreateEx (CheckedEnc () ByteString))
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString))
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString
 -> CheckedEnc () ByteString)
-> Either
     RecreateEx
     (Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString)
-> Either RecreateEx (CheckedEnc () ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString
-> CheckedEnc () ByteString
forall (xs :: [Symbol]) c str.
SymbolList xs =>
Enc @[Symbol] xs c str -> CheckedEnc c str
toCheckedEnc) (Maybe
   (Either
      RecreateEx
      (Enc
         @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString))
 -> Maybe (Either RecreateEx (CheckedEnc () ByteString)))
-> (ByteString
    -> Maybe
         (Either
            RecreateEx
            (Enc
               @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString)))
-> ByteString
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms nms c str, SymbolList nms) =>
UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
forall (f :: * -> *) c str.
(Monad f,
 ValidateAll
   f
   ((':) @Symbol "r-UTF8" ('[] @Symbol))
   ((':) @Symbol "r-UTF8" ('[] @Symbol))
   c
   str,
 SymbolList ((':) @Symbol "r-UTF8" ('[] @Symbol))) =>
UncheckedEnc c str
-> Maybe
     (f (Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) c str))
check @'["r-UTF8"] (UncheckedEnc () ByteString
 -> Maybe
      (Either
         RecreateEx
         (Enc
            @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString)))
-> (ByteString -> UncheckedEnc () ByteString)
-> ByteString
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> UncheckedEnc () ByteString
forall str. str -> UncheckedEnc () str
unchecked
              try5 :: ByteString -> Maybe (Either RecreateEx (CheckedEnc () ByteString))
try5 = (Either
   RecreateEx
   (Enc
      @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString)
 -> Either RecreateEx (CheckedEnc () ByteString))
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString))
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Enc @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString
 -> CheckedEnc () ByteString)
-> Either
     RecreateEx
     (Enc
        @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString)
-> Either RecreateEx (CheckedEnc () ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Enc @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString
-> CheckedEnc () ByteString
forall (xs :: [Symbol]) c str.
SymbolList xs =>
Enc @[Symbol] xs c str -> CheckedEnc c str
toCheckedEnc) (Maybe
   (Either
      RecreateEx
      (Enc
         @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString))
 -> Maybe (Either RecreateEx (CheckedEnc () ByteString)))
-> (ByteString
    -> Maybe
         (Either
            RecreateEx
            (Enc
               @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString)))
-> ByteString
-> Maybe (Either RecreateEx (CheckedEnc () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (nms :: [Symbol]) (f :: * -> *) c str.
(Monad f, ValidateAll f nms nms c str, SymbolList nms) =>
UncheckedEnc c str -> Maybe (f (Enc @[Symbol] nms c str))
forall (f :: * -> *) c str.
(Monad f,
 ValidateAll
   f
   ((':) @Symbol "enc-B64" ('[] @Symbol))
   ((':) @Symbol "enc-B64" ('[] @Symbol))
   c
   str,
 SymbolList ((':) @Symbol "enc-B64" ('[] @Symbol))) =>
UncheckedEnc c str
-> Maybe
     (f (Enc @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) c str))
check @'["enc-B64"] (UncheckedEnc () ByteString
 -> Maybe
      (Either
         RecreateEx
         (Enc
            @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString)))
-> (ByteString -> UncheckedEnc () ByteString)
-> ByteString
-> Maybe
     (Either
        RecreateEx
        (Enc
           @[Symbol] ((':) @Symbol "enc-B64" ('[] @Symbol)) () ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> UncheckedEnc () ByteString
forall str. str -> UncheckedEnc () str
unchecked
              def :: Either RecreateEx b
def =  RecreateEx -> Either RecreateEx b
forall a b. a -> Either a b
Left (RecreateEx -> Either RecreateEx b)
-> RecreateEx -> Either RecreateEx b
forall a b. (a -> b) -> a -> b
$ String -> RecreateEx
forall e. Show e => e -> RecreateEx
recreateErrUnknown (String
"Invalid Header " String -> ShowS
forall a. [a] -> [a] -> [a]
++ PartHeader -> String
forall a. Show a => a -> String
show PartHeader
parth) 


-- | 
-- Example decodes parts of email that are base 64 encoded text and nothing else.
--
-- This provides a type safety assurance that we do not decode certain parts of email
-- (like trying to decode base 64 on a plain text part).
--
-- >>> decodeB64ForTextOnly <$> recreateEncoding tstEmail
-- Right (SimplifiedEmailF {emailHeader = "Some Header", parts = [UnsafeMkCheckedEnc ["enc-B64"] () "U29tZSBBU0NJSSBUZXh0",UnsafeMkCheckedEnc ["r-ASCII"] () "Some ASCII Text",UnsafeMkCheckedEnc ["r-UTF8"] () "Some UTF8 Text",UnsafeMkCheckedEnc ["r-ASCII"] () "Some ASCII plain text"]})
--
-- Combinator @fromCheckedEnc \@'["enc-B64", "r-UTF8"]@ acts as a selector and picks only the
-- @["enc-B64", "r-UTF8"]@ values from our 'Traversable' type. 
--
-- We play the ('<|>') game on all the selectors we want picking and decoding right pieces only.
--
-- Imagine this is one of the pieces:
--
-- >>> let piece = unsafeCheckedEnc ["enc-B64","r-ASCII"] () ("U29tZSBBU0NJSSBUZXh0" :: B.ByteString)
-- >>> displ piece
-- "UnsafeMkCheckedEnc [enc-B64,r-ASCII] () (ByteString U29tZSBBU0NJSSBUZXh0)"
--
-- This code will not pick it up:
--
-- >>> fromCheckedEnc @'["enc-B64", "r-UTF8"] $ piece
-- Nothing
--
-- But this one will:
--
-- >>> fromCheckedEnc @'["enc-B64", "r-ASCII"]  $ piece
-- Just (UnsafeMkEnc Proxy () "U29tZSBBU0NJSSBUZXh0")
--
-- so we can apply the decoding on the selected piece 
--
-- >>> fmap (toCheckedEnc . decodePart @'["enc-B64"]) . fromCheckedEnc @'["enc-B64", "r-ASCII"] $ piece
-- Just (UnsafeMkCheckedEnc ["r-ASCII"] () "Some ASCII Text")

decodeB64ForTextOnly :: SimplifiedEmailEncB -> SimplifiedEmailEncB
decodeB64ForTextOnly :: SimplifiedEmailEncB -> SimplifiedEmailEncB
decodeB64ForTextOnly = (CheckedEnc () ByteString -> CheckedEnc () ByteString)
-> SimplifiedEmailEncB -> SimplifiedEmailEncB
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((CheckedEnc () ByteString
 -> Maybe (CheckedEnc () ByteString) -> CheckedEnc () ByteString)
-> [CheckedEnc () ByteString -> Maybe (CheckedEnc () ByteString)]
-> CheckedEnc () ByteString
-> CheckedEnc () ByteString
forall (f :: * -> *) a b.
Alternative f =>
(a -> f b -> b) -> [a -> f b] -> a -> b
runAlternatives CheckedEnc () ByteString
-> Maybe (CheckedEnc () ByteString) -> CheckedEnc () ByteString
forall a. a -> Maybe a -> a
fromMaybe [CheckedEnc () ByteString -> Maybe (CheckedEnc () ByteString)
forall c.
CheckedEnc c ByteString -> Maybe (CheckedEnc c ByteString)
tryUtf8, CheckedEnc () ByteString -> Maybe (CheckedEnc () ByteString)
forall c.
CheckedEnc c ByteString -> Maybe (CheckedEnc c ByteString)
tryAscii]) 
  where
    tryUtf8, tryAscii :: CheckedEnc c B.ByteString -> Maybe (CheckedEnc c B.ByteString)
    tryUtf8 :: CheckedEnc c ByteString -> Maybe (CheckedEnc c ByteString)
tryUtf8 = (Enc
   @[Symbol]
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
   c
   ByteString
 -> CheckedEnc c ByteString)
-> Maybe
     (Enc
        @[Symbol]
        ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
        c
        ByteString)
-> Maybe (CheckedEnc c ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) c ByteString
-> CheckedEnc c ByteString
forall (xs :: [Symbol]) c str.
SymbolList xs =>
Enc @[Symbol] xs c str -> CheckedEnc c str
toCheckedEnc (Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) c ByteString
 -> CheckedEnc c ByteString)
-> (Enc
      @[Symbol]
      ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
      c
      ByteString
    -> Enc
         @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) c ByteString)
-> Enc
     @[Symbol]
     ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
     c
     ByteString
-> CheckedEnc c ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
  c
  ByteString
-> Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) c ByteString
forall c.
Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
  c
  ByteString
-> Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) c ByteString
decodeToUtf8) (Maybe
   (Enc
      @[Symbol]
      ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
      c
      ByteString)
 -> Maybe (CheckedEnc c ByteString))
-> (CheckedEnc c ByteString
    -> Maybe
         (Enc
            @[Symbol]
            ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
            c
            ByteString))
-> CheckedEnc c ByteString
-> Maybe (CheckedEnc c ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (xs :: [Symbol]) c str.
SymbolList xs =>
CheckedEnc c str -> Maybe (Enc @[Symbol] xs c str)
forall c str.
SymbolList
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol))) =>
CheckedEnc c str
-> Maybe
     (Enc
        @[Symbol]
        ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
        c
        str)
fromCheckedEnc @'["enc-B64", "r-UTF8"] 
    tryAscii :: CheckedEnc c ByteString -> Maybe (CheckedEnc c ByteString)
tryAscii = (Enc
   @[Symbol]
   ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
   c
   ByteString
 -> CheckedEnc c ByteString)
-> Maybe
     (Enc
        @[Symbol]
        ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
        c
        ByteString)
-> Maybe (CheckedEnc c ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Enc @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) c ByteString
-> CheckedEnc c ByteString
forall (xs :: [Symbol]) c str.
SymbolList xs =>
Enc @[Symbol] xs c str -> CheckedEnc c str
toCheckedEnc (Enc @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) c ByteString
 -> CheckedEnc c ByteString)
-> (Enc
      @[Symbol]
      ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
      c
      ByteString
    -> Enc
         @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) c ByteString)
-> Enc
     @[Symbol]
     ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
     c
     ByteString
-> CheckedEnc c ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
  c
  ByteString
-> Enc
     @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) c ByteString
forall c.
Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
  c
  ByteString
-> Enc
     @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) c ByteString
decodeToAscii) (Maybe
   (Enc
      @[Symbol]
      ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
      c
      ByteString)
 -> Maybe (CheckedEnc c ByteString))
-> (CheckedEnc c ByteString
    -> Maybe
         (Enc
            @[Symbol]
            ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
            c
            ByteString))
-> CheckedEnc c ByteString
-> Maybe (CheckedEnc c ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (xs :: [Symbol]) c str.
SymbolList xs =>
CheckedEnc c str -> Maybe (Enc @[Symbol] xs c str)
forall c str.
SymbolList
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol))) =>
CheckedEnc c str
-> Maybe
     (Enc
        @[Symbol]
        ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
        c
        str)
fromCheckedEnc @'["enc-B64", "r-ASCII"] 
 
    decodeToUtf8 :: Enc '["enc-B64", "r-UTF8"] c B.ByteString -> _
    decodeToUtf8 :: Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-UTF8" ('[] @Symbol)))
  c
  ByteString
-> Enc @[Symbol] ((':) @Symbol "r-UTF8" ('[] @Symbol)) c ByteString
decodeToUtf8 = forall (xs :: [Symbol]) (xsf :: [Symbol]) c str.
DecodeAll Identity xs xs c str =>
Enc @[Symbol] (Append @Symbol xs xsf) c str
-> Enc @[Symbol] xsf c str
forall (xsf :: [Symbol]) c str.
DecodeAll
  Identity
  ((':) @Symbol "enc-B64" ('[] @Symbol))
  ((':) @Symbol "enc-B64" ('[] @Symbol))
  c
  str =>
Enc
  @[Symbol]
  (Append @Symbol ((':) @Symbol "enc-B64" ('[] @Symbol)) xsf)
  c
  str
-> Enc @[Symbol] xsf c str
decodePart @'["enc-B64"]

    decodeToAscii :: Enc '["enc-B64", "r-ASCII"] c B.ByteString -> _
    decodeToAscii :: Enc
  @[Symbol]
  ((':) @Symbol "enc-B64" ((':) @Symbol "r-ASCII" ('[] @Symbol)))
  c
  ByteString
-> Enc
     @[Symbol] ((':) @Symbol "r-ASCII" ('[] @Symbol)) c ByteString
decodeToAscii = forall (xs :: [Symbol]) (xsf :: [Symbol]) c str.
DecodeAll Identity xs xs c str =>
Enc @[Symbol] (Append @Symbol xs xsf) c str
-> Enc @[Symbol] xsf c str
forall (xsf :: [Symbol]) c str.
DecodeAll
  Identity
  ((':) @Symbol "enc-B64" ('[] @Symbol))
  ((':) @Symbol "enc-B64" ('[] @Symbol))
  c
  str =>
Enc
  @[Symbol]
  (Append @Symbol ((':) @Symbol "enc-B64" ('[] @Symbol)) xsf)
  c
  str
-> Enc @[Symbol] xsf c str
decodePart @'["enc-B64"]


-- * Helpers

-- | Provides easy to read encoding information
instance Displ a => Displ (IpV4F a) where
    displ :: IpV4F a -> String
displ = IpV4F String -> String
forall a. Show a => a -> String
show (IpV4F String -> String)
-> (IpV4F a -> IpV4F String) -> IpV4F a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> String) -> IpV4F a -> IpV4F String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> String
forall x. Displ x => x -> String
displ

-- | Provides easy to read encoding information
instance Displ a => Displ (SimplifiedEmailF a) where
    displ :: SimplifiedEmailF a -> String
displ = SimplifiedEmailF String -> String
forall a. Show a => a -> String
show (SimplifiedEmailF String -> String)
-> (SimplifiedEmailF a -> SimplifiedEmailF String)
-> SimplifiedEmailF a
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> String) -> SimplifiedEmailF a -> SimplifiedEmailF String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> String
forall x. Displ x => x -> String
displ    

runAlternatives' :: Alternative f => (f b -> b) -> [a -> f b] -> a -> b
runAlternatives' :: (f b -> b) -> [a -> f b] -> a -> b
runAlternatives' f b -> b
defF [a -> f b]
fns = f b -> b
defF (f b -> b) -> (a -> f b) -> a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a -> f b] -> a -> f b
forall (f :: * -> *) a b. Alternative f => [a -> f b] -> a -> f b
alternatives [a -> f b]
fns

runAlternatives :: Alternative f => (a -> f b -> b) -> [a -> f b] -> a -> b
runAlternatives :: (a -> f b -> b) -> [a -> f b] -> a -> b
runAlternatives a -> f b -> b
defF [a -> f b]
fns a
a = a -> f b -> b
defF a
a (f b -> b) -> (a -> f b) -> a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a -> f b] -> a -> f b
forall (f :: * -> *) a b. Alternative f => [a -> f b] -> a -> f b
alternatives [a -> f b]
fns (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
$ a
a

alternatives :: Alternative f => [a -> f b] -> a -> f b
alternatives :: [a -> f b] -> a -> f b
alternatives [a -> f b]
fns a
a = ((a -> f b) -> f b -> f b) -> f b -> [a -> f b] -> f b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (f b -> f b -> f b
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>) (f b -> f b -> f b)
-> ((a -> f b) -> f b) -> (a -> f b) -> f b -> f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> f b) -> a -> f b
forall a b. (a -> b) -> a -> b
$ a
a)) f b
forall (f :: * -> *) a. Alternative f => f a
empty [a -> f b]
fns