# Understanding the Decoder type

**URL:** <https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188>\
**Category:** Learn\
**Created:** [April 28, 2018, 8:51pm UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188 "2018-04-28T20:51:48Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![luizpvasc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/luizpvasc/32/916_2.png) [@luizpvasc](https://discourse.elm-lang.org/u/luizpvasc)\
**Post date:** [April 28, 2018, 8:51pm UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/1 "2018-04-28T20:51:48Z")

</div>

Hello everyone!

I’m still a beginner in Elm but also in typed functional programming in general, so sorry in advance if this question sounds weird. I came across the `Json.Decode.Decoder` type while reading the Todo MVC’s [source code](https://github.com/evancz/elm-todomvc), and I went to look at the [type definition](https://github.com/elm-lang/json/blob/master/src/Json/Decode.elm):

```
{-| A value that knows how to decode JSON values.
-}
type Decoder a = Decoder

```

… which doesn’t make much sense to me. Is the `Decoder` on the right a different thing from the `Decoder` on the left? I then looked the definition of `Json.Decode.succeed` and `Json.Decode.fail` and got more confused because they seem (?) to return the same type: `Decoder a`.

As a parallel, the `Result` type makes sense to me, it has either a success or error value. But the decoder seems to be the same for both `succeed` and `fail`? Maybe there are some concepts I still need to learn in order to understand this.

If anyone could point me in the right direction that would be great, thanks!

---

<div class="post-metadata">

**Author:** ![folkertdev](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/folkertdev/32/133_2.png) [@folkertdev](https://discourse.elm-lang.org/u/folkertdev)\
**Post date:** [April 28, 2018, 9:27pm UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/2 "2018-04-28T21:27:29Z")

</div>

The Decoder functionality is implemented in what is called Kernel code - the javascript underlying elm.  
The compiler cannot typecheck javascript code, but we still need types on the elm side.

For instance, a few lines below that definition, we see

```elm
string : Decoder String
string =
  Elm.Kernel.Json.decodeString

```

The compiler cannot verify that we give the correct type to `string`: it will accept any type (and we could lie about the type). So, we create an empty type (there is one constructor, but it is never used and not exposed) to give types to the decoder primitives (like `string` and `int` but also `map` and `andThen`). These types then make sure that our elm code defines valid decoders.

But conceptually, the decoder could be defined as

```elm
type Decoder a = Decoder (String -> Result DecoderError a)

```

> [@luizpvasc](#):
>
> Is the Decoder on the right a different thing from the Decoder on the left?

Yes, the left one is a type, the right one is a value. so this would be valid code

```auto
type A = A 

a : A -- value `a` has type `A`
a = A -- value `a` is equal to `A`

```

> [@luizpvasc](#):
>
> I then looked the definition of Json.Decode.succeed and Json.Decode.fail and got more confused because they seem (?) to return the same type: Decoder a

That is really because the error is always a string. I hope this makes more sense given the elm-definition of `Decoder`, which which you can define

```auto
succeed : a -> Decoder a 
succeed value = Decoder (\_ -> Ok value)

fail : String -> Decoder a 
fail error = Decoder (\_ -> Err error)

```

---

<div class="post-metadata">

**Author:** ![luizpvasc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/luizpvasc/32/916_2.png) [@luizpvasc](https://discourse.elm-lang.org/u/luizpvasc)\
**Post date:** [April 28, 2018, 10:28pm UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/3 "2018-04-28T22:28:45Z")

</div>

Thank you a lot, I didn’t know about Kernel code.

If I may ask another question about types and values, when you have a lower case in the type it means it can hold anything, right? For example (from the Elm guides) `type List a = Empty | Node a List`. But in the decoder example it only appears on the left: `type Decoder a = Decoder`.

As an example, I can declare my own type with `type Val a = Val`, but it throws an error when I try to call with any value:

```
`Val` is not a function, but you are giving it an argument. 

```

It seems the `a` in the type doesn’t change anything, so I could as well declare it as `type Val = Val`. Am I missing something or is this something specific for Kernel code?

---

<div class="post-metadata">

**Author:** ![joelq](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joelq/32/445_2.png) [@joelq](https://discourse.elm-lang.org/u/joelq)\
**Post date:** [April 28, 2018, 11:29pm UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/4 "2018-04-28T23:29:10Z")

</div>

Declaring a type like `type Val a = Val` is a fancy trick called a **phantom type**. We’re parameterizing the _type_ even though we’re not using the parameter in the _value_. This allows us to do fancy things like:

```elm
stringVal : Val String
stringVal =
  Val

boolVal : Val Bool
boolVal =
  Val

boolValsOnly : Val Bool -> String
boolValsOnly val =
  "Val Bool only!"

```

The compiler will allow `boolValsOnly boolVal` but will **reject** `boolValsOnly stringVal`. Even though under the hood, both `boolVal` and `stringVal` have the exact same implementation, the compiler sees these as having different types (because of the explicit signature).

Cool party trick but what’s the use? You’ll see it in the core library when a type needs to be parameterized but the actual implementation is done with kernel code. It’s also used in some libraries like [elm-tagged](http://package.elm-lang.org/packages/joneshf/elm-tagged/2.1.0/Tagged) to give some extra type safety allow the compiler to know that your number is associated with a particular unit.

Check out this article for [more on phantom types](https://medium.com/@ckoster22/advanced-types-in-elm-phantom-types-808044c5946d).

Don’t worry if this all seems bit mind-bending. It’s not something you’ll come across often in day-to-day Elm 😃

---

<div class="post-metadata">

**Author:** ![joelq](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joelq/32/445_2.png) [@joelq](https://discourse.elm-lang.org/u/joelq)\
**Post date:** [April 28, 2018, 11:50pm UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/5 "2018-04-28T23:50:36Z")

</div>

BTW, if you’re interested in getting a conceptual understanding of what the `Json.Decode.Decoder` and `Json.Decode.Value` types mean under the hood, this [series of articles](https://8thlight.com/blog/kofi-gumbs/2017/06/28/elm-json-decoding-types.html) walks through implementing your own in pure Elm.

While fun and educational, it’s worth noting that you absolutely can master the concept of decoders without knowing how they work under the hood. If you’re newer to Elm/decoders, I’d recommend getting a feel for the various ways you can decode json and combine simple decoders into more complex ones before diving too deeply into how they’re implemented 😃

**Some resources on decoders:**

It’s worth starting with the [official guide](https://guide.elm-lang.org/interop/json.html).

For more reading on decoders:

- [5 Common Decoding Situations](https://robots.thoughtbot.com/5-common-json-decoders) beyond just some JSON and an Elm record with the exact same shape/types.
- [Decoding JSON from the inside-out](https://www.brianthicks.com/post/2017/08/30/breaking-out-of-deeply-nested-json-objects/)
- A series of [katas that walk through building decoders](https://github.com/zwilias/elm-demystify-decoders). Starts basic and works up to more complex ones.
- [Combining simple structures into more complex ones](https://robots.thoughtbot.com/elms-universal-pattern). Looks at `Maybe`, `List`, `Random.Generator` and `Json.Decode.Decoder`.

---

<div class="post-metadata">

**Author:** ![luizpvasc](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/luizpvasc/32/916_2.png) [@luizpvasc](https://discourse.elm-lang.org/u/luizpvasc)\
**Post date:** [April 28, 2018, 11:55pm UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/6 "2018-04-28T23:55:19Z")

</div>

Thanks for the phantom types explanation and the articles.

Really appreciated 😄

---

<div class="post-metadata">

**Author:** ![mattpiz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/mattpiz/32/860_2.png) [@mattpiz](https://discourse.elm-lang.org/u/mattpiz)\
**Post date:** [April 29, 2018, 4:37am UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/7 "2018-04-29T04:37:18Z")

</div>

I must link this fantastic article explaining how you could have created the Json.Decode library and the Decoder type step by step:

> [@New blog post: You could have designed the Json.Decode library!](https://discourse.elm-lang.org/t/new-blog-post-you-could-have-designed-the-json-decode-library/120):
>
> At elm-conf I had a weird idea about writing a universal JSON decoder that decoded JSON into a generic JsonValue type. I noodled with it for a while and realized that my experimentation didn’t yield any crazy new tech but did help me understand why Json.Decoder works the way it does better than anything I’d seen previously. I just published a blog post that explains what I learned: [https://dev.to/matthewsj/you-could-have-designed-the-jsondecode-library-2d8](https://dev.to/matthewsj/you-could-have-designed-the-jsondecode-library-2d8) I’d love to hear what you think about i…

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [May 9, 2018, 4:37am UTC](https://discourse.elm-lang.org/t/understanding-the-decoder-type/1188/8 "2018-05-09T04:37:18Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
