Search code examples
elmcolon-equals

Elm Colon Equals Operator


When attempting to decode larger json values, I've ran into the following code in the Json-Decode-Extra library. (located here)

import Date (Date)

type alias User =
  { id                : Int
  , createdAt         : Date
  , updatedAt         : Date
  , deletedAt         : Maybe Date
  , username          : Maybe String
  , email             : Maybe String
  , fullname          : Maybe String
  , avatar            : Maybe String
  , isModerator       : Bool
  , isOrganization    : Bool
  , isAdmin           : Bool
  }

metaDecoder : (Int -> Date -> Date -> Maybe Date -> b) -> Decoder b
metaDecoder f = f
  `map`      ("id"        := int)
  `apply` ("createdAt" := date)
  `apply` ("updatedAt" := date)
  `apply` ("deletedAt" := maybe date)

userDecoder : Decoder User
userDecoder = metaDecoder User
  `apply` ("username"          := maybe string)
  `apply` ("email"             := maybe string)
  `apply` ("fullname"          := maybe string)
  `apply` ("avatar"            := maybe string)
  `apply` ("isModerator"       := bool)
  `apply` ("isOrganization"    := bool)
  `apply` ("isAdmin"           := bool)

However, I'm constantly running into a compiler error for the := operator. Where is this defined? The JSON decode tutorials don't explicitly import this operator anywhere.


Solution

  • In Elm 0.18, the := operator was replaced by Json.Decode.field, and using backticks for infix operators was removed.

    You are using a package (circuithub/elm-json-extra) which has not been updated to Elm 0.18.

    Consider switching to use the package maintained by the Elm community: elm-community/json-extra. You can use andMap instead of apply. Here is your example code upgraded to the new library and Elm 0.18:

    import Date exposing (Date)
    import Json.Decode exposing (..)
    import Json.Decode.Extra exposing (andMap, date)
    
    metaDecoder : (Int -> Date -> Date -> Maybe Date -> b) -> Decoder b
    metaDecoder f =
        succeed f
            |> andMap (field "id" int)
            |> andMap (field "createdAt" date)
            |> andMap (field "updatedAt" date)
            |> andMap (field "deletedAt" (maybe date))
    
    userDecoder : Decoder User
    userDecoder =
        metaDecoder User
            |> andMap (field "username" (maybe string))
            |> andMap (field "email" (maybe string))
            |> andMap (field "fullname" (maybe string))
            |> andMap (field "avatar" (maybe string))
            |> andMap (field "isModerator" bool)
            |> andMap (field "isOrganization" bool)
            |> andMap (field "isAdmin" bool)
    

    Note that the elm-community/json-extra package also exports an infix operator |: which is an infix version of andMap. You could use this to make your code more concise. For example:

    metaDecoder : (Int -> Date -> Date -> Maybe Date -> b) -> Decoder b
    metaDecoder f =
        succeed f
            |: field "id" int
            |: field "createdAt" date
            |: field "updatedAt" date
            |: field "deletedAt" (maybe date)