Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elm: How to Json decode a Union Type with a single TypeConstructor?

As seen in following code, it is easy to decode UserAlias but the moment I try to decode UserType i.e. Replace D.map2 UserAlias with D.map2 UserType Compiler cries out loud. How do I fix this compiler error?

import Json.Decode as D
import Html exposing (..)
import Result as R

type  UserType = UserType {name:String, age:Int}

type alias UserAlias = {name:String, age:Int}


userDecoder = D.map2 UserAlias
                (D.field "name" D.string)
                (D.field "age" D.int)


decodeUser json = D.decodeString userDecoder json 


json = """
  { "name": "Bob", "age": 40 }
"""


main = div [] [(text << toString << decodeUser) json]

Above code works fine. Now replace D.map2 UserAlias with D.map2 UserType

And compiler cries

Detected errors in 1 module.
==================================== ERRORS ====================================



-- TYPE MISMATCH ---------------------------------------------------------------

The 2nd argument to function `map2` is causing a mismatch.

13|               D.map2 UserType
14|>                (D.field "name" D.string)
15|                 (D.field "age" D.int)

Function `map2` is expecting the 2nd argument to be:

    D.Decoder { age : Int, name : String }

But it is:

    D.Decoder String

Hint: I always figure out the type of arguments from left to right. If an
argument is acceptable when I check it, I assume it is "correct" in subsequent
checks. So the problem may actually be in how previous arguments interact with
the 2nd.



-- TYPE MISMATCH ---------------------------------------------------------------

The 1st argument to function `map2` is causing a mismatch.

13|>              D.map2 UserType
14|                 (D.field "name" D.string)
15|                 (D.field "age" D.int)

Function `map2` is expecting the 1st argument to be:

    { age : Int, name : String } -> b -> UserType

But it is:

    { age : Int, name : String } -> UserType

Hint: It looks like a function needs 1 more argument.

How do I fix this error, please help!

Basically I nolonger wish to use type alias, and only user UserType so that I can hide internal record structure, and refactor it without breaking the public API.

thanks.

like image 813
Jigar Avatar asked Dec 05 '25 19:12

Jigar


1 Answers

The UserType constructor takes a single parameter of UserAlias, so we can simply use Json.Decode.map inside your existing decoder to take the UserAlias value and construct a decoder for UserType like this:

userDecoder : D.Decoder UserType
userDecoder = D.map2 UserAlias
                (D.field "name" D.string)
                (D.field "age" D.int)
                |> D.map UserType
like image 61
Chad Gilbert Avatar answered Dec 08 '25 15:12

Chad Gilbert