<commit_before>homepage: https://github.com/Holmusk/elm-street
changelog-type: markdown
hash: 493abe4b1837060e3d5320cc4c711a2d21927bbf0ebbb591a11b2774264d2abd
test-bench-deps:
  bytestring: ^>=0.10
  base: ! '>=4.11.1.0 && <4.13'
  hspec: ^>=2.7.1
  types: -any
  elm-street: -any
  aeson: -any
maintainer: Holmusk <<EMAIL>>
synopsis: Crossing the road between Haskell and Elm
changelog: |
  # Changelog

  `elm-street` uses [PVP Versioning][1].
  The changelog is available [on GitHub][2].

  ##  0.1.0.1 — Sep 6, 2019

  * Fix newtype qualified import bug in `Types.elm` generated module.
  * Allow `pretty-printer-1.3` version.

  ## 0.1.0.0 — Sep 6, 2019

  * [#80](https://github.com/holmusk/elm-street/issues/80):
    **Important:** *All* encoders for constructors with fields now have `tag` due
    to aeson decoder on Haskell side.

    **Migration guide 1:** Rename fields that will have `tag` name on the Elm
    side.

    **Migration guide 2:** If you have manual `ToJSON` instances that communicate
    with Elm via generated decoders, you need to add `tag` field with the
    constructor name:

    ```haskell
    data User = User { ... }

    instance ToJSON User where
        toJSON = [ "tag" .= ("User" :: Text), ... ]
    ```

  * [#71](https://github.com/holmusk/elm-street/issues/71):
    **Breaking change:** Remove **overlapping** instance for `String`.

    **Migration guide:** Use `Text` instead of `String`.

  * [#70](https://github.com/holmusk/elm-street/issues/70):
    Use qualified imports of generated types and function in Elm generated files.
  * [#74](https://github.com/holmusk/elm-street/issues/74):
    Fix unit type `typeRef` encoder and decoder printers.
  * [#72](https://github.com/holmusk/elm-street/issues/72):
    Use consistent encoders and decoders for unary constructors.
  * [#79](https://github.com/holmusk/elm-street/issues/79):
    Implement cross-language golden tests.
  * [#76](https://github.com/holmusk/elm-street/issues/76):
    Support GHC-8.6.5. Use common stanzas.
  * [#86](https://github.com/holmusk/elm-street/issues/86):
    Refactor `Elm.Print` module and split into multiple smaller modules.
  * [#73](https://github.com/holmusk/elm-street/issues/73):
    Clarify the restriction with reserved words in documentation.
  * [#90](https://github.com/Holmusk/elm-street/issues/90)
    Support converting 3-tuples.
  * [#6](https://github.com/holmusk/elm-street/issues/6):
    Test generated Elm code on CI.

  ## 0.0.1 — Mar 29, 2019

  * [#64](https://github.com/holmusk/elm-street/issues/64):
    Fix indentation for the generated enums.
  * [#66](https://github.com/holmusk/elm-street/issues/66):
    Patch JSON encoders and decoders for sum types with a single field.

  ## 0.0.0

  * Initially created.

  [1]: https://pvp.haskell.org
  [2]: https://github.com/Holmusk/elm-street/releases
basic-deps:
  warp: ^>=3.2
  wai: ^>=3.2
  base: ! '>=4.11.1.0 && <4.13'
  time: -any
  text: ==1.2.*
  filepath: ==1.4.*
  types: -any
  servant-server: ! '>=0.14 && <0.17'
  servant: ! '>=0.14 && <0.17'
  elm-street: -any
  prettyprinter: ! '>=1.2.1 && <1.4'
  aeson: ! '>=1.3'
  directory: ==1.3.*
all-versions:
- 0.0.0
- 0.0.1
- 0.1.0.1
author: <NAME>, <NAME>
latest: 0.1.0.1
description-type: markdown
description: |
  # elm-street

  [![Hackage](https://img.shields.io/hackage/v/elm-street.svg)](https://hackage.haskell.org/package/elm-street)
  [![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)
  [![Stackage Lts](http://stackage.org/package/elm-street/badge/lts)](http://stackage.org/lts/package/elm-street)
  [![Stackage Nightly](http://stackage.org/package/elm-street/badge/nightly)](http://stackage.org/nightly/package/elm-street)

  Crossing the road between Haskell and Elm.

  ## What this library about?

  `Elm-street` allows you to generate automatically derived from Haskell types
  definitions of Elm data types, JSON encoders and decoders. This helps to avoid
  writing and maintaining huge chunk of boilerplate code when developing full-stack
  applications.

  ## Getting started

  In order to use `elm-street` features, you need to perform the following steps:

  1. Add `elm-street` to the dependencies of your Haskell package.
  2. Derive the `Elm` typeclass for relevant data types. You also need to derive
     JSON instances according to `elm-street` naming scheme.
     This can be done like this:
     ```haskell
     import Elm (Elm, elmStreetParseJson, elmStreetToJson)

     data User = User
         { userName :: Text
         , userAge  :: Int
         } deriving (Generic)
           deriving anyclass (Elm)

     instance ToJSON   User where toJSON = elmStreetToJson
     instance FromJSON User where parseJSON = elmStreetParseJson
     ```
     > **NOTE:** This requires extensions `-XDerivingStrategies`, `-XDeriveGeneric`, `-XDeriveAnyClass`.

     Alternatively you can use `-XDerivingVia` to remove some boilerplate (available since GHC 8.6.1):
     ```haskell
     import Elm (Elm, ElmStreet (..))

     data User = User
         { userName :: Text
         , userAge  :: Int
         } deriving (Generic)
           deriving (Elm, ToJSON, FromJSON) via ElmStreet User
     ```
  3. Create list of all types you want to expose to Elm:
     ```haskell
     type Types =
        '[ User
         , Status
         ]
     ```
     > **NOTE:** This requires extension `-XDataKinds`.
  4. Use `generateElm` function to output definitions to specified directory under
     specified module prefix.
     ```
     main :: IO ()
     main = generateElm @Types $ defaultSettings "frontend/src" ["Core", "Generated"]
     ```
     > **NOTE:** This requires extension `-XTypeApplications`.

     The above command when called generates the following files:

       + `frontend/src/Core/Generated/Types.elm`: `Core.Generated.Types` module with the definitions of all types
       + `frontend/src/Core/Generated/Encoder.elm`: `Core.Generated.Encoder` module with the JSON encoders for the types
       + `frontend/src/Core/Generated/Decoder.elm`: `Core.Generated.Decoder` module with the JSON decoders for the types
       + `frontend/src/Core/Generated/ElmStreet.elm`: `Core.Generated.ElmStreet` module with bundled helper functions

  ## Elm-side preparations

  If you want to use capabilities provided by `elm-street` in your Elm
  application, you need to have several Elm packages preinstalled in the project. You
  can install them with the following commands:

  ```shell
  elm install elm/time
  elm install elm/json
  elm install NoRedInk/elm-json-decode-pipeline
  elm install rtfeldman/elm-iso8601-date-strings
  ```

  ## Library restrictions

  `Elm-street` is **not** trying to be as general as possible and support every
  use-case. The library is opinionated in some decisions and contains several
  limitations, specifically:

  1. Record fields must be prefixed with the type name or its abbreviation.
     ```haskell
     data UserStatus = UserStatus
         { userStatusId      :: Id
         , userStatusRemarks :: Text
         }

     data HealthReading = HealthReading
         { hrUser   :: User
         , hrDate   :: UTCTime
         , hrWeight :: Double
         }
     ```
  2. Data types with type variables are not supported (see [issue #45](https://github.com/Holmusk/elm-street/issues/45) for more details).
     Though, if type variables are phantom, you still can implement `Elm` instance which
     will generate valid Elm defintions. Here is how you can create `Elm` instance for
     `newtype`s with phantom type variables:
     ```haskell
     newtype Id a = Id { unId :: Text }

     instance Elm (Id a) where
         toElmDefinition _ = elmNewtype @Text "Id" "unId"
     ```
  3. Sum types with records are not supported (because it's a bad practice to have
     records in sum types).
     ```haskell
     -- - Not supported
     data Address
         = Post { postCode :: Text }
         | Full { fullStreet :: Text, fullHouse :: Int }

     ```
  4. Sum types with more than 8 fields in at least one constructor are not
     supported.
     ```haskell
     -- - Not supported
     data Foo
         = Bar Int Text
         | Baz Int Int Text Text Double Double Bool Bool Char
     ```
  5. Records with fields that reference the type itself are not supported. This
     limitation is due to the fact that `elm-street` generates `type alias` for
     record data type. So the generated Elm type for the following Haskell data
     type won't compile in Elm:
     ```haskell
     data User = User
         { userName      :: Text
         , userFollowers :: [User]
         }
     ```
  6. Generated JSON encoders and decoders are consistent with default behavior of
     derived `ToJSON/FromJSON` instances from the `aeson` library except you need
     to strip record field prefixes. Fortunately, this also can be done
     generically. You can use functions from `Elm.Aeson` module to derive `JSON`
     instances from the `aeson` package.
  7. Only `UTCTime` Haskell data type is supported and it's translated to `Posix`
     type in Elm.
  8. Some words in Elm are considered reserved and naming a record field with one of these words (prefixed with the type name, see 1) will result in the generated Elm files to not compile. So, the following words should not be used as field names:
     * `if`
     * `then`
     * `else`
     * `case`
     * `of`
     * `let`
     * `in`
     * `type`
     * `module`
     * `where`
     * `import`
     * `exposing`
     * `as`
     * `port`
     * `tag` (reserved for constructor name due to `aeson` options)
  9. For newtypes `FromJSON` and `ToJSON` instances should be derived using `newtype` strategy. And `Elm` should be derived using `anyclass` strategy:
     ```haskell
     newtype Newtype = Newtype Int
         deriving newtype (FromJSON, ToJSON)
         deriving anyclass (Elm)
     ```

  ## Play with frontend example

  The `frontend` directory contains example of minimal Elm project that shows how
  generated types are used. To play with this project, do:

  1. Build and execute the `generate-elm` binary:
     ```
     cabal new-run generate-elm
     ```
  2. Run Haskell backend:
     ```
     cabal new-run run-backend
     ```
  3. In separate terminal tab go to the `frontend` folder:
     ```
     cd frontend
     ```
  4. Run the frontend:
     ```
     elm-app start
     ```

  ## Generated examples

  Below you can see some examples of how Haskell data types are converted to Elm
  types with JSON encoders and decoders using the `elm-street` library.

  ### Records

  **Haskell**

  ```haskell
  data User = User
      { userName :: Text
      , userAge  :: Int
      } deriving (Generic)
        deriving (Elm, ToJSON, FromJSON) via ElmStreet User
  ```

  **Elm**

  ```elm
  type alias User =
      { name : String
      , age : Int
      }

  encodeUser : User -> Value
  encodeUser x = E.object
      [ ("name", E.string x.name)
      , ("age", E.int x.age)
      ]

  decodeUser : Decoder User
  decodeUser = D.succeed User
      |> required "name" D.string
      |> required "age" D.int
  ```

  ### Enums

  **Haskell**

  ```haskell
  data RequestStatus
      = Approved
      | Rejected
      | Reviewing
      deriving (Generic)
      deriving (Elm, ToJSON, FromJSON) via ElmStreet RequestStatus
  ```

  **Elm**

  ```elm
  type RequestStatus
      = Approved
      | Rejected
      | Reviewing

  showRequestStatus : RequestStatus -> String
  showRequestStatus x = case x of
      Approved -> "Approved"
      Rejected -> "Rejected"
      Reviewing -> "Reviewing"

  readRequestStatus : String -> Maybe RequestStatus
  readRequestStatus x = case x of
      "Approved" -> Just Approved
      "Rejected" -> Just Rejected
      "Reviewing" -> Just Reviewing
      _ -> Nothing

  universeRequestStatus : List RequestStatus
  universeRequestStatus = [Approved, Rejected, Reviewing]

  encodeRequestStatus : RequestStatus -> Value
  encodeRequestStatus = E.string << showRequestStatus

  decodeRequestStatus : Decoder RequestStatus
  decodeRequestStatus = elmStreetDecodeEnum readRequestStatus
  ```

  ### Newtypes

  **Haskell**

  ```haskell
  newtype Age = Age
      { unAge :: Int
      } deriving (Generic)
        deriving newtype (FromJSON, ToJSON)
        deriving anyclass (Elm)
  ```

  **Elm**

  ```elm
  type alias Age =
      { age : Int
      }

  encodeAge : Age -> Value
  encodeAge x = E.int x.age

  decodeAge : Decoder Age
  decodeAge = D.map Age D.int
  ```

  ### Newtypes with phantom types

  **Haskell**

  ```haskell
  newtype Id a = Id
      { unId :: Text
      } deriving (Generic)
        deriving newtype (FromJSON, ToJSON)

  instance Elm (Id a) where
      toElmDefinition _ = elmNewtype @Text "Id" "unId"
  ```

  **Elm**

  ```elm
  type alias Id =
      { unId : String
      }

  encodeId : Id -> Value
  encodeId x = E.string x.unId

  decodeId : Decoder Id
  decodeId = D.map Id D.string
  ```

  ### Sum types

  **Haskell**

  ```haskell
  data Guest
      = Regular Text Int
      | Visitor Text
      | Blocked
      deriving (Generic)
      deriving (Elm, ToJSON, FromJSON) via ElmStreet Guest
  ```

  **Elm**

  ```elm
  type Guest
      = Regular String Int
      | Visitor String
      | Blocked

  encodeGuest : Guest -> Value
  encodeGuest x = E.object <| case x of
      Regular x1 x2 -> [("tag", E.string "Regular"), ("contents", E.list identity [E.string x1, E.int x2])]
      Visitor x1 -> [("tag", E.string "Visitor"), ("contents", E.string x1)]
      Blocked  -> [("tag", E.string "Blocked"), ("contents", E.list identity [])]

  decodeGuest : Decoder Guest
  decodeGuest =
      let decide : String -> Decoder Guest
          decide x = case x of
              "Regular" -> D.field "contents" <| D.map2 Regular (D.index 0 D.string) (D.index 1 D.int)
              "Visitor" -> D.field "contents" <| D.map Visitor D.string
              "Blocked" -> D.succeed Blocked
              c -> D.fail <| "Guest doesn't have such constructor: " ++ c
      in D.andThen decide (D.field "tag" D.string)
  ```
license-name: MPL-2.0
<commit_msg>Update from Hackage at 2019-09-13T06:34:06Z<commit_after>homepage: https://github.com/Holmusk/elm-street
changelog-type: markdown
hash: f5f2fd14a680731baa02523b70a1b6fe8560eae130e467bf3d48b97f79f056cd
test-bench-deps:
  bytestring: ^>=0.10
  base: ! '>=4.11.1.0 && <4.13'
  hspec: ^>=2.7.1
  types: -any
  elm-street: -any
  aeson: -any
maintainer: Holmusk <<EMAIL>>
synopsis: Crossing the road between Haskell and Elm
changelog: |
  # Changelog

  `elm-street` uses [PVP Versioning][1].
  The changelog is available [on GitHub][2].

  ##  0.1.0.2 — Sep 13, 2019

  * [#89](https://github.com/holmusk/elm-street/issues/89):
    Regulate parenthesis on complicated types in encoder, decoder and type
    generation.

  ##  0.1.0.1 — Sep 6, 2019

  * Fix newtype qualified import bug in `Types.elm` generated module.
  * Allow `pretty-printer-1.3` version.

  ## 0.1.0.0 — Sep 6, 2019

  * [#80](https://github.com/holmusk/elm-street/issues/80):
    **Important:** *All* encoders for constructors with fields now have `tag` due
    to aeson decoder on Haskell side.

    **Migration guide 1:** Rename fields that will have `tag` name on the Elm
    side.

    **Migration guide 2:** If you have manual `ToJSON` instances that communicate
    with Elm via generated decoders, you need to add `tag` field with the
    constructor name:

    ```haskell
    data User = User { ... }

    instance ToJSON User where
        toJSON = [ "tag" .= ("User" :: Text), ... ]
    ```

  * [#71](https://github.com/holmusk/elm-street/issues/71):
    **Breaking change:** Remove **overlapping** instance for `String`.

    **Migration guide:** Use `Text` instead of `String`.

  * [#70](https://github.com/holmusk/elm-street/issues/70):
    Use qualified imports of generated types and function in Elm generated files.
  * [#74](https://github.com/holmusk/elm-street/issues/74):
    Fix unit type `typeRef` encoder and decoder printers.
  * [#72](https://github.com/holmusk/elm-street/issues/72):
    Use consistent encoders and decoders for unary constructors.
  * [#79](https://github.com/holmusk/elm-street/issues/79):
    Implement cross-language golden tests.
  * [#76](https://github.com/holmusk/elm-street/issues/76):
    Support GHC-8.6.5. Use common stanzas.
  * [#86](https://github.com/holmusk/elm-street/issues/86):
    Refactor `Elm.Print` module and split into multiple smaller modules.
  * [#73](https://github.com/holmusk/elm-street/issues/73):
    Clarify the restriction with reserved words in documentation.
  * [#90](https://github.com/Holmusk/elm-street/issues/90)
    Support converting 3-tuples.
  * [#6](https://github.com/holmusk/elm-street/issues/6):
    Test generated Elm code on CI.

  ## 0.0.1 — Mar 29, 2019

  * [#64](https://github.com/holmusk/elm-street/issues/64):
    Fix indentation for the generated enums.
  * [#66](https://github.com/holmusk/elm-street/issues/66):
    Patch JSON encoders and decoders for sum types with a single field.

  ## 0.0.0

  * Initially created.

  [1]: https://pvp.haskell.org
  [2]: https://github.com/Holmusk/elm-street/releases
basic-deps:
  warp: ^>=3.2
  wai: ^>=3.2
  base: ! '>=4.11.1.0 && <4.13'
  time: -any
  text: ==1.2.*
  filepath: ==1.4.*
  types: -any
  servant-server: ! '>=0.14 && <0.17'
  servant: ! '>=0.14 && <0.17'
  elm-street: -any
  prettyprinter: ! '>=1.2.1 && <1.4'
  aeson: ! '>=1.3'
  directory: ==1.3.*
all-versions:
- 0.0.0
- 0.0.1
- 0.1.0.1
- 0.1.0.2
author: <NAME>, <NAME>
latest: 0.1.0.2
description-type: markdown
description: |
  # elm-street

  [![Hackage](https://img.shields.io/hackage/v/elm-street.svg)](https://hackage.haskell.org/package/elm-street)
  [![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)
  [![Stackage Lts](http://stackage.org/package/elm-street/badge/lts)](http://stackage.org/lts/package/elm-street)
  [![Stackage Nightly](http://stackage.org/package/elm-street/badge/nightly)](http://stackage.org/nightly/package/elm-street)

  Crossing the road between Haskell and Elm.

  ## What this library about?

  `Elm-street` allows you to generate automatically derived from Haskell types
  definitions of Elm data types, JSON encoders and decoders. This helps to avoid
  writing and maintaining huge chunk of boilerplate code when developing full-stack
  applications.

  ## Getting started

  In order to use `elm-street` features, you need to perform the following steps:

  1. Add `elm-street` to the dependencies of your Haskell package.
  2. Derive the `Elm` typeclass for relevant data types. You also need to derive
     JSON instances according to `elm-street` naming scheme.
     This can be done like this:
     ```haskell
     import Elm (Elm, elmStreetParseJson, elmStreetToJson)

     data User = User
         { userName :: Text
         , userAge  :: Int
         } deriving (Generic)
           deriving anyclass (Elm)

     instance ToJSON   User where toJSON = elmStreetToJson
     instance FromJSON User where parseJSON = elmStreetParseJson
     ```
     > **NOTE:** This requires extensions `-XDerivingStrategies`, `-XDeriveGeneric`, `-XDeriveAnyClass`.

     Alternatively you can use `-XDerivingVia` to remove some boilerplate (available since GHC 8.6.1):
     ```haskell
     import Elm (Elm, ElmStreet (..))

     data User = User
         { userName :: Text
         , userAge  :: Int
         } deriving (Generic)
           deriving (Elm, ToJSON, FromJSON) via ElmStreet User
     ```
  3. Create list of all types you want to expose to Elm:
     ```haskell
     type Types =
        '[ User
         , Status
         ]
     ```
     > **NOTE:** This requires extension `-XDataKinds`.
  4. Use `generateElm` function to output definitions to specified directory under
     specified module prefix.
     ```
     main :: IO ()
     main = generateElm @Types $ defaultSettings "frontend/src" ["Core", "Generated"]
     ```
     > **NOTE:** This requires extension `-XTypeApplications`.

     The above command when called generates the following files:

       + `frontend/src/Core/Generated/Types.elm`: `Core.Generated.Types` module with the definitions of all types
       + `frontend/src/Core/Generated/Encoder.elm`: `Core.Generated.Encoder` module with the JSON encoders for the types
       + `frontend/src/Core/Generated/Decoder.elm`: `Core.Generated.Decoder` module with the JSON decoders for the types
       + `frontend/src/Core/Generated/ElmStreet.elm`: `Core.Generated.ElmStreet` module with bundled helper functions

  ## Elm-side preparations

  If you want to use capabilities provided by `elm-street` in your Elm
  application, you need to have several Elm packages preinstalled in the project. You
  can install them with the following commands:

  ```shell
  elm install elm/time
  elm install elm/json
  elm install NoRedInk/elm-json-decode-pipeline
  elm install rtfeldman/elm-iso8601-date-strings
  ```

  ## Library restrictions

  `Elm-street` is **not** trying to be as general as possible and support every
  use-case. The library is opinionated in some decisions and contains several
  limitations, specifically:

  1. Record fields must be prefixed with the type name or its abbreviation.
     ```haskell
     data UserStatus = UserStatus
         { userStatusId      :: Id
         , userStatusRemarks :: Text
         }

     data HealthReading = HealthReading
         { hrUser   :: User
         , hrDate   :: UTCTime
         , hrWeight :: Double
         }
     ```
  2. Data types with type variables are not supported (see [issue #45](https://github.com/Holmusk/elm-street/issues/45) for more details).
     Though, if type variables are phantom, you still can implement `Elm` instance which
     will generate valid Elm defintions. Here is how you can create `Elm` instance for
     `newtype`s with phantom type variables:
     ```haskell
     newtype Id a = Id { unId :: Text }

     instance Elm (Id a) where
         toElmDefinition _ = elmNewtype @Text "Id" "unId"
     ```
  3. Sum types with records are not supported (because it's a bad practice to have
     records in sum types).
     ```haskell
     -- - Not supported
     data Address
         = Post { postCode :: Text }
         | Full { fullStreet :: Text, fullHouse :: Int }

     ```
  4. Sum types with more than 8 fields in at least one constructor are not
     supported.
     ```haskell
     -- - Not supported
     data Foo
         = Bar Int Text
         | Baz Int Int Text Text Double Double Bool Bool Char
     ```
  5. Records with fields that reference the type itself are not supported. This
     limitation is due to the fact that `elm-street` generates `type alias` for
     record data type. So the generated Elm type for the following Haskell data
     type won't compile in Elm:
     ```haskell
     data User = User
         { userName      :: Text
         , userFollowers :: [User]
         }
     ```
  6. Generated JSON encoders and decoders are consistent with default behavior of
     derived `ToJSON/FromJSON` instances from the `aeson` library except you need
     to strip record field prefixes. Fortunately, this also can be done
     generically. You can use functions from `Elm.Aeson` module to derive `JSON`
     instances from the `aeson` package.
  7. Only `UTCTime` Haskell data type is supported and it's translated to `Posix`
     type in Elm.
  8. Some words in Elm are considered reserved and naming a record field with one of these words (prefixed with the type name, see 1) will result in the generated Elm files to not compile. So, the following words should not be used as field names:
     * `if`
     * `then`
     * `else`
     * `case`
     * `of`
     * `let`
     * `in`
     * `type`
     * `module`
     * `where`
     * `import`
     * `exposing`
     * `as`
     * `port`
     * `tag` (reserved for constructor name due to `aeson` options)
  9. For newtypes `FromJSON` and `ToJSON` instances should be derived using `newtype` strategy. And `Elm` should be derived using `anyclass` strategy:
     ```haskell
     newtype Newtype = Newtype Int
         deriving newtype (FromJSON, ToJSON)
         deriving anyclass (Elm)
     ```

  ## Play with frontend example

  The `frontend` directory contains example of minimal Elm project that shows how
  generated types are used. To play with this project, do:

  1. Build and execute the `generate-elm` binary:
     ```
     cabal new-run generate-elm
     ```
  2. Run Haskell backend:
     ```
     cabal new-run run-backend
     ```
  3. In separate terminal tab go to the `frontend` folder:
     ```
     cd frontend
     ```
  4. Run the frontend:
     ```
     elm-app start
     ```

  ## Generated examples

  Below you can see some examples of how Haskell data types are converted to Elm
  types with JSON encoders and decoders using the `elm-street` library.

  ### Records

  **Haskell**

  ```haskell
  data User = User
      { userName :: Text
      , userAge  :: Int
      } deriving (Generic)
        deriving (Elm, ToJSON, FromJSON) via ElmStreet User
  ```

  **Elm**

  ```elm
  type alias User =
      { name : String
      , age : Int
      }

  encodeUser : User -> Value
  encodeUser x = E.object
      [ ("name", E.string x.name)
      , ("age", E.int x.age)
      ]

  decodeUser : Decoder User
  decodeUser = D.succeed User
      |> required "name" D.string
      |> required "age" D.int
  ```

  ### Enums

  **Haskell**

  ```haskell
  data RequestStatus
      = Approved
      | Rejected
      | Reviewing
      deriving (Generic)
      deriving (Elm, ToJSON, FromJSON) via ElmStreet RequestStatus
  ```

  **Elm**

  ```elm
  type RequestStatus
      = Approved
      | Rejected
      | Reviewing

  showRequestStatus : RequestStatus -> String
  showRequestStatus x = case x of
      Approved -> "Approved"
      Rejected -> "Rejected"
      Reviewing -> "Reviewing"

  readRequestStatus : String -> Maybe RequestStatus
  readRequestStatus x = case x of
      "Approved" -> Just Approved
      "Rejected" -> Just Rejected
      "Reviewing" -> Just Reviewing
      _ -> Nothing

  universeRequestStatus : List RequestStatus
  universeRequestStatus = [Approved, Rejected, Reviewing]

  encodeRequestStatus : RequestStatus -> Value
  encodeRequestStatus = E.string << showRequestStatus

  decodeRequestStatus : Decoder RequestStatus
  decodeRequestStatus = elmStreetDecodeEnum readRequestStatus
  ```

  ### Newtypes

  **Haskell**

  ```haskell
  newtype Age = Age
      { unAge :: Int
      } deriving (Generic)
        deriving newtype (FromJSON, ToJSON)
        deriving anyclass (Elm)
  ```

  **Elm**

  ```elm
  type alias Age =
      { age : Int
      }

  encodeAge : Age -> Value
  encodeAge x = E.int x.age

  decodeAge : Decoder Age
  decodeAge = D.map Age D.int
  ```

  ### Newtypes with phantom types

  **Haskell**

  ```haskell
  newtype Id a = Id
      { unId :: Text
      } deriving (Generic)
        deriving newtype (FromJSON, ToJSON)

  instance Elm (Id a) where
      toElmDefinition _ = elmNewtype @Text "Id" "unId"
  ```

  **Elm**

  ```elm
  type alias Id =
      { unId : String
      }

  encodeId : Id -> Value
  encodeId x = E.string x.unId

  decodeId : Decoder Id
  decodeId = D.map Id D.string
  ```

  ### Sum types

  **Haskell**

  ```haskell
  data Guest
      = Regular Text Int
      | Visitor Text
      | Blocked
      deriving (Generic)
      deriving (Elm, ToJSON, FromJSON) via ElmStreet Guest
  ```

  **Elm**

  ```elm
  type Guest
      = Regular String Int
      | Visitor String
      | Blocked

  encodeGuest : Guest -> Value
  encodeGuest x = E.object <| case x of
      Regular x1 x2 -> [("tag", E.string "Regular"), ("contents", E.list identity [E.string x1, E.int x2])]
      Visitor x1 -> [("tag", E.string "Visitor"), ("contents", E.string x1)]
      Blocked  -> [("tag", E.string "Blocked"), ("contents", E.list identity [])]

  decodeGuest : Decoder Guest
  decodeGuest =
      let decide : String -> Decoder Guest
          decide x = case x of
              "Regular" -> D.field "contents" <| D.map2 Regular (D.index 0 D.string) (D.index 1 D.int)
              "Visitor" -> D.field "contents" <| D.map Visitor D.string
              "Blocked" -> D.succeed Blocked
              c -> D.fail <| "Guest doesn't have such constructor: " ++ c
      in D.andThen decide (D.field "tag" D.string)
  ```
license-name: MPL-2.0

{'fraction_non_alphanumeric': 0.1171003717472119, 'fraction_numerical': 0.018061303219471136, 'mean_word_length': 2.6779311234360894, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 85, 'https://': 41, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 14, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '330891', 'n_tokens_mistral': 9610, 'n_tokens_neox': 8822, 'n_words': 2908}