{- | Pretty-printing functions for @Encoder.elm@ module.
Also contains encoders for common types which go to the @ElmStreet.elm@ module.
-}

module Elm.Print.Encoder
       ( prettyShowEncoder

         -- * Standard missing encoders
       , encodeMaybe
       , encodeEither
       , encodePair
       , encodeTriple
       ) where

import Data.List.NonEmpty (NonEmpty, toList)
import Data.Text (Text)
import Data.Text.Prettyprint.Doc (Doc, brackets, colon, comma, concatWith, dquotes, emptyDoc,
                                  equals, lbracket, line, nest, parens, pretty, rbracket, surround,
                                  vsep, (<+>))

import Elm.Ast (ElmAlias (..), ElmConstructor (..), ElmDefinition (..), ElmPrim (..),
                ElmRecordField (..), ElmType (..), TypeName (..), TypeRef (..), isEnum)
import Elm.Print.Common (arrow, mkQualified, qualifiedTypeWithVarsDoc, showDoc, wrapParens)

import qualified Data.List.NonEmpty as NE
import qualified Data.Text as T


{- | Returns the encoder for the given type.


TODO

 +-------------------+------------------+------------------+--------------------+
 |    Haskell Type   |     Eml Type     |     Encoder      |       JSON         |
 +===================+==================+==================+====================+
 |   'Int'           |      'Int'       | standard encoder |                    |
 +-------------------+------------------+------------------+--------------------+

-}
prettyShowEncoder :: ElmDefinition -> Text
prettyShowEncoder :: ElmDefinition -> Text
prettyShowEncoder ElmDefinition
def = Doc Any -> Text
forall ann. Doc ann -> Text
showDoc (Doc Any -> Text) -> Doc Any -> Text
forall a b. (a -> b) -> a -> b
$ case ElmDefinition
def of
    DefAlias ElmAlias
elmAlias -> ElmAlias -> Doc Any
forall ann. ElmAlias -> Doc ann
aliasEncoderDoc ElmAlias
elmAlias
    DefType ElmType
elmType   -> ElmType -> Doc Any
forall ann. ElmType -> Doc ann
typeEncoderDoc ElmType
elmType
    DefPrim ElmPrim
_         -> Doc Any
forall ann. Doc ann
emptyDoc

-- | Encoder for 'ElmType' (which is either enum or the Sum type).
typeEncoderDoc :: ElmType -> Doc ann
typeEncoderDoc :: ElmType -> Doc ann
typeEncoderDoc t :: ElmType
t@ElmType{Bool
[Text]
Text
NonEmpty ElmConstructor
elmTypeConstructors :: ElmType -> NonEmpty ElmConstructor
elmTypeIsNewtype :: ElmType -> Bool
elmTypeVars :: ElmType -> [Text]
elmTypeName :: ElmType -> Text
elmTypeConstructors :: NonEmpty ElmConstructor
elmTypeIsNewtype :: Bool
elmTypeVars :: [Text]
elmTypeName :: Text
..} =
    -- function defenition: @encodeTypeName : TypeName -> Value@.
       Text -> [Text] -> Doc ann
forall ann. Text -> [Text] -> Doc ann
encoderDef Text
elmTypeName [Text]
elmTypeVars
    Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
forall ann. Doc ann
line
    Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> if ElmType -> Bool
isEnum ElmType
t
       -- if this is Enum just using the show instance we wrote.
       then Doc ann
forall ann. Doc ann
enumEncoder
       else if Bool
elmTypeIsNewtype
            -- if this is type with one constructor and one field then it should just call encoder for wrapped type
            then Doc ann
forall ann. Doc ann
newtypeEncoder
            -- If it sum type then it should look like: @{"tag": "Foo", "contents" : ["string", 1]}@
            else Doc ann
forall ann. Doc ann
sumEncoder
  where
    enumEncoder :: Doc ann
    enumEncoder :: Doc ann
enumEncoder = Doc ann
forall ann. Doc ann
name Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
equals Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"E.string << T.show" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
elmTypeName

    newtypeEncoder :: Doc ann
    newtypeEncoder :: Doc ann
newtypeEncoder =
        Doc ann
forall ann. Doc ann
name Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
equals Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
fieldEncoderDoc Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"<< T.un" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
elmTypeName
      where
        fieldEncoderDoc :: Doc ann
        fieldEncoderDoc :: Doc ann
fieldEncoderDoc = case ElmConstructor -> [TypeRef]
elmConstructorFields (ElmConstructor -> [TypeRef]) -> ElmConstructor -> [TypeRef]
forall a b. (a -> b) -> a -> b
$ NonEmpty ElmConstructor -> ElmConstructor
forall a. NonEmpty a -> a
NE.head NonEmpty ElmConstructor
elmTypeConstructors of
            []    -> Doc ann
"ERROR"
            TypeRef
f : [TypeRef]
_ -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
f)

    sumEncoder :: Doc ann
    sumEncoder :: Doc ann
sumEncoder = Int -> Doc ann -> Doc ann
forall ann. Int -> Doc ann -> Doc ann
nest Int
4
        (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$ [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
vsep
        ([Doc ann] -> Doc ann) -> [Doc ann] -> Doc ann
forall a b. (a -> b) -> a -> b
$ (Doc ann
forall ann. Doc ann
name Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"x" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
equals Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"E.object <| case x of")
        Doc ann -> [Doc ann] -> [Doc ann]
forall a. a -> [a] -> [a]
: (ElmConstructor -> Doc ann) -> [ElmConstructor] -> [Doc ann]
forall a b. (a -> b) -> [a] -> [b]
map ElmConstructor -> Doc ann
forall ann. ElmConstructor -> Doc ann
mkCase (NonEmpty ElmConstructor -> [ElmConstructor]
forall a. NonEmpty a -> [a]
toList NonEmpty ElmConstructor
elmTypeConstructors)

    -- | Encoder function name
    name :: Doc ann
    name :: Doc ann
name = Text -> Doc ann
forall ann. Text -> Doc ann
encoderName Text
elmTypeName

    -- | Create case clouse for each of the sum Constructors.
    mkCase :: ElmConstructor -> Doc ann
    mkCase :: ElmConstructor -> Doc ann
mkCase ElmConstructor{[TypeRef]
Text
elmConstructorName :: ElmConstructor -> Text
elmConstructorFields :: [TypeRef]
elmConstructorName :: Text
elmConstructorFields :: ElmConstructor -> [TypeRef]
..} = Text -> Doc ann
forall ann. Text -> Doc ann
mkQualified Text
elmConstructorName
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
vars
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
arrow
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
brackets (Text -> Doc ann
forall ann. Text -> Doc ann
mkTag Text
elmConstructorName Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
forall ann. Doc ann
contents)
      where
        -- | Creates variables: @x1@ to @xN@, where N is the number of the constructor fields.
        fields :: [Doc ann]
        fields :: [Doc ann]
fields = Int -> [Doc ann] -> [Doc ann]
forall a. Int -> [a] -> [a]
take ([TypeRef] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TypeRef]
elmConstructorFields) ([Doc ann] -> [Doc ann]) -> [Doc ann] -> [Doc ann]
forall a b. (a -> b) -> a -> b
$
            (Int -> Doc ann) -> [Int] -> [Doc ann]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty (Text -> Doc ann) -> (Int -> Text) -> Int -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Int -> Text
mkText Text
"x") [Int
1..]

        contents :: Doc ann
        contents :: Doc ann
contents = Doc ann
"," Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
parens (Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
dquotes Doc ann
"contents" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
forall ann. Doc ann
comma Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
contentsEnc)

        -- JSON encoder for the "contents" key
        contentsEnc :: Doc ann
        contentsEnc :: Doc ann
contentsEnc = case [TypeRef]
elmConstructorFields of
            [TypeRef
_] -> Doc ann
forall ann. Doc ann
fieldEncs
            [TypeRef]
_   -> Doc ann
"E.list identity" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
brackets Doc ann
forall ann. Doc ann
fieldEncs

        -- | @encoderA x1@
        fieldEncs :: Doc ann
        fieldEncs :: Doc ann
fieldEncs = (Doc ann -> Doc ann -> Doc ann) -> [Doc ann] -> Doc ann
forall (t :: * -> *) ann.
Foldable t =>
(Doc ann -> Doc ann -> Doc ann) -> t (Doc ann) -> Doc ann
concatWith (Doc ann -> Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann -> Doc ann
surround Doc ann
", ") ([Doc ann] -> Doc ann) -> [Doc ann] -> Doc ann
forall a b. (a -> b) -> a -> b
$
            (Doc ann -> Doc ann -> Doc ann)
-> [Doc ann] -> [Doc ann] -> [Doc ann]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
(<+>) ((TypeRef -> Doc ann) -> [TypeRef] -> [Doc ann]
forall a b. (a -> b) -> [a] -> [b]
map (Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (Doc ann -> Doc ann) -> (TypeRef -> Doc ann) -> TypeRef -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder) [TypeRef]
elmConstructorFields) [Doc ann]
forall ann. [Doc ann]
fields

        -- | Makes variable like: @x11@ etc.
        mkText :: Text -> Int -> Text
        mkText :: Text -> Int -> Text
mkText Text
x Int
i = Text
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
i)

        vars :: Doc ann
        vars :: Doc ann
vars =  (Doc ann -> Doc ann -> Doc ann) -> [Doc ann] -> Doc ann
forall (t :: * -> *) ann.
Foldable t =>
(Doc ann -> Doc ann -> Doc ann) -> t (Doc ann) -> Doc ann
concatWith (Doc ann -> Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann -> Doc ann
surround Doc ann
" ") [Doc ann]
forall ann. [Doc ann]
fields


aliasEncoderDoc :: ElmAlias -> Doc ann
aliasEncoderDoc :: ElmAlias -> Doc ann
aliasEncoderDoc ElmAlias{Bool
Text
NonEmpty ElmRecordField
elmAliasIsNewtype :: ElmAlias -> Bool
elmAliasFields :: ElmAlias -> NonEmpty ElmRecordField
elmAliasName :: ElmAlias -> Text
elmAliasIsNewtype :: Bool
elmAliasFields :: NonEmpty ElmRecordField
elmAliasName :: Text
..} =
    Text -> [Text] -> Doc ann
forall ann. Text -> [Text] -> Doc ann
encoderDef Text
elmAliasName []
    Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
forall ann. Doc ann
line
    Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> if Bool
elmAliasIsNewtype
       then Doc ann
forall ann. Doc ann
newtypeEncoder
       else Doc ann
forall ann. Doc ann
recordEncoder
  where
    newtypeEncoder :: Doc ann
    newtypeEncoder :: Doc ann
newtypeEncoder = Doc ann
forall ann. Doc ann
leftPart Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> ElmRecordField -> Doc ann
forall ann. ElmRecordField -> Doc ann
fieldEncoderDoc (NonEmpty ElmRecordField -> ElmRecordField
forall a. NonEmpty a -> a
NE.head NonEmpty ElmRecordField
elmAliasFields)

    recordEncoder :: Doc ann
    recordEncoder :: Doc ann
recordEncoder = Int -> Doc ann -> Doc ann
forall ann. Int -> Doc ann -> Doc ann
nest Int
4
        (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$ [Doc ann] -> Doc ann
forall ann. [Doc ann] -> Doc ann
vsep
        ([Doc ann] -> Doc ann) -> [Doc ann] -> Doc ann
forall a b. (a -> b) -> a -> b
$ (Doc ann
forall ann. Doc ann
leftPart Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"E.object")
        Doc ann -> [Doc ann] -> [Doc ann]
forall a. a -> [a] -> [a]
: NonEmpty ElmRecordField -> [Doc ann]
forall ann. NonEmpty ElmRecordField -> [Doc ann]
fieldsEncode NonEmpty ElmRecordField
elmAliasFields

    leftPart :: Doc ann
    leftPart :: Doc ann
leftPart = Text -> Doc ann
forall ann. Text -> Doc ann
encoderName Text
elmAliasName Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"x" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
equals

    fieldsEncode :: NonEmpty ElmRecordField -> [Doc ann]
    fieldsEncode :: NonEmpty ElmRecordField -> [Doc ann]
fieldsEncode NonEmpty ElmRecordField
fields =
        Doc ann
forall ann. Doc ann
lbracket Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Text -> Doc ann
forall ann. Text -> Doc ann
mkTag Text
elmAliasName
      Doc ann -> [Doc ann] -> [Doc ann]
forall a. a -> [a] -> [a]
: (ElmRecordField -> Doc ann) -> [ElmRecordField] -> [Doc ann]
forall a b. (a -> b) -> [a] -> [b]
map ((Doc ann
forall ann. Doc ann
comma Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+>) (Doc ann -> Doc ann)
-> (ElmRecordField -> Doc ann) -> ElmRecordField -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ElmRecordField -> Doc ann
forall ann. ElmRecordField -> Doc ann
recordFieldDoc) (NonEmpty ElmRecordField -> [ElmRecordField]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty ElmRecordField
fields)
     [Doc ann] -> [Doc ann] -> [Doc ann]
forall a. [a] -> [a] -> [a]
++ [Doc ann
forall ann. Doc ann
rbracket]

    recordFieldDoc :: ElmRecordField -> Doc ann
    recordFieldDoc :: ElmRecordField -> Doc ann
recordFieldDoc field :: ElmRecordField
field@ElmRecordField{Text
TypeRef
elmRecordFieldName :: ElmRecordField -> Text
elmRecordFieldType :: ElmRecordField -> TypeRef
elmRecordFieldName :: Text
elmRecordFieldType :: TypeRef
..} = Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
parens (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$
            Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
dquotes (Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
elmRecordFieldName)
         Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
forall ann. Doc ann
comma
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> ElmRecordField -> Doc ann
forall ann. ElmRecordField -> Doc ann
fieldEncoderDoc ElmRecordField
field

    fieldEncoderDoc :: ElmRecordField -> Doc ann
    fieldEncoderDoc :: ElmRecordField -> Doc ann
fieldEncoderDoc ElmRecordField{Text
TypeRef
elmRecordFieldName :: Text
elmRecordFieldType :: TypeRef
elmRecordFieldName :: ElmRecordField -> Text
elmRecordFieldType :: ElmRecordField -> TypeRef
..} =
        Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
elmRecordFieldType) Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"x." Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
elmRecordFieldName

-- | Create pair of view: @("tag", E.string "SomeName")@.
mkTag :: Text -> Doc ann
mkTag :: Text -> Doc ann
mkTag Text
txt = Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
parens (Doc ann -> Doc ann) -> Doc ann -> Doc ann
forall a b. (a -> b) -> a -> b
$ Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
dquotes Doc ann
"tag" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
forall ann. Doc ann
comma Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"E.string" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
dquotes (Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
txt)

-- | The definition of the @encodeTYPENAME@ function.
encoderDef
    :: Text  -- ^ Type name
    -> [Text] -- ^ List of type variables
    -> Doc ann
encoderDef :: Text -> [Text] -> Doc ann
encoderDef Text
typeName [Text]
vars =
    Text -> Doc ann
forall ann. Text -> Doc ann
encoderName Text
typeName
    Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
colon
    Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Text -> [Text] -> Doc ann
forall ann. Text -> [Text] -> Doc ann
qualifiedTypeWithVarsDoc Text
typeName [Text]
vars
    Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
forall ann. Doc ann
arrow
    Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"Value"

-- | Create the name of the encoder function.
encoderName :: Text -> Doc ann
encoderName :: Text -> Doc ann
encoderName Text
typeName = Doc ann
"encode" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
typeName

-- | Converts the reference to the existing type to the corresponding encoder.
typeRefEncoder :: TypeRef -> Doc ann
typeRefEncoder :: TypeRef -> Doc ann
typeRefEncoder (RefCustom TypeName{Text
unTypeName :: TypeName -> Text
unTypeName :: Text
..}) = Doc ann
"encode" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty ((Char -> Bool) -> Text -> Text
T.takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' ') Text
unTypeName)
typeRefEncoder (RefPrim ElmPrim
elmPrim) = case ElmPrim
elmPrim of
    ElmPrim
ElmUnit         -> Doc ann
"always <| E.list identity []"
    ElmPrim
ElmNever        -> Doc ann
"never"
    ElmPrim
ElmBool         -> Doc ann
"E.bool"
    ElmPrim
ElmChar         -> Doc ann
"E.string << String.fromChar"
    ElmPrim
ElmInt          -> Doc ann
"E.int"
    ElmPrim
ElmFloat        -> Doc ann
"E.float"
    ElmPrim
ElmString       -> Doc ann
"E.string"
    ElmPrim
ElmTime         -> Doc ann
"Iso.encode"
    ElmMaybe TypeRef
t      -> Doc ann
"elmStreetEncodeMaybe"
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
t)
    ElmResult TypeRef
l TypeRef
r   -> Doc ann
"elmStreetEncodeEither"
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
l)
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
r)
    ElmPair TypeRef
a TypeRef
b     -> Doc ann
"elmStreetEncodePair"
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
a)
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
b)
    ElmTriple TypeRef
a TypeRef
b TypeRef
c -> Doc ann
"elmStreetEncodeTriple"
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
a)
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
b)
        Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
c)
    ElmList TypeRef
l       -> Doc ann
"E.list" Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann
wrapParens (TypeRef -> Doc ann
forall ann. TypeRef -> Doc ann
typeRefEncoder TypeRef
l)

-- | @JSON@ encoder Elm help function for 'Maybe's.
encodeMaybe :: Text
encodeMaybe :: Text
encodeMaybe = [Text] -> Text
T.unlines
    [ Text
"elmStreetEncodeMaybe : (a -> Value) -> Maybe a -> Value"
    , Text
"elmStreetEncodeMaybe enc = Maybe.withDefault E.null << Maybe.map enc"
    ]

-- | @JSON@ encoder Elm help function for 'Either's.
encodeEither :: Text
encodeEither :: Text
encodeEither = [Text] -> Text
T.unlines
    [ Text
"elmStreetEncodeEither : (a -> Value) -> (b -> Value) -> Result a b -> Value"
    , Text
"elmStreetEncodeEither encA encB res = E.object <| case res of"
    , Text
"    Err a -> [(\"Left\",  encA a)]"
    , Text
"    Ok b  -> [(\"Right\", encB b)]"
    ]

-- | @JSON@ encoder Elm help function for 2-tuples.
encodePair :: Text
encodePair :: Text
encodePair = [Text] -> Text
T.unlines
    [ Text
"elmStreetEncodePair : (a -> Value) -> (b -> Value) -> (a, b) -> Value"
    , Text
"elmStreetEncodePair encA encB (a, b) = E.list identity [encA a, encB b]"
    ]

-- | @JSON@ encoder Elm help function for 3-tuples.
encodeTriple :: Text
encodeTriple :: Text
encodeTriple = [Text] -> Text
T.unlines
    [ Text
"elmStreetEncodeTriple : (a -> Value) -> (b -> Value) -> (c -> Value) -> (a, b, c) -> Value"
    , Text
"elmStreetEncodeTriple encA encB encC (a, b, c) = E.list identity [encA a, encB b, encC c]"
    ]