I had to do this myself recently. The general solution is that for any 
recursive definition you have to have a lambda between the definition and 
it's use.

Your example 1 does this in the decoder with the call to `lazy`. Example 2 
doesn't, so it fails. I've heard (but haven't checked) that the compiler 
will catch this in 0.18.

I also wrote about my 
case: 
https://www.brianthicks.com/post/2016/11/07/happy-little-trees-decoding-recursive-data-structures-in-elm/

On Wednesday, October 5, 2016 at 5:19:32 PM UTC-5, Wil C wrote:
>
> Ok, figured it out for one of two ways. Posted here for future confused 
> people doing recursive data structures.
>
> I've read 
> https://github.com/elm-lang/elm-compiler/blob/0.17.1/hints/recursive-alias.md#obvious-but-kind-of-annoying
> and there's two ways of putting it together. The first way is to make the 
> node a type. The second way is to make the node a type alias (and the 
> recursion a type). I only figured it out for the first 
>
> 1) When node is a type.
>
> type Node = Node {
>     name : String
>   , children : List Node
>   }
>
> fromJson : Json.Value -> Result String Node
> fromJson json =
>   decodeValue nodeDecoder json
>
> nodeByNameChildren : String -> List Node -> Node
> nodeByNameChildren name children =
>   Node { name = name, children = children }
>
> nodeDecoder : Decoder Node
> nodeDecoder =
>   object2 nodeByNameChildren
>     ("name" := string)
>     ("children" := list (lazy (\_ -> nodeDecoder)))
>
> However, like the link above says, it's a bit annoying to have the type 
> annotation 
> <https://github.com/elm-lang/elm-compiler/blob/0.17.1/hints/recursive-alias.md#less-obvious-but-nicer>
>  
> that you need to break out of every time you need to update the record.
>
> 2) When node is a type alias
>
> In this case, the model would be:
>
> type alias Node = {
>     name : String
>   , children : Children
>   }
>
> type Children =
>   Children (List Node)
>
> nodeDecoder : Decoder Node
> nodeDecoder =
>   object2 Node
>     ("name" := string)
>     ("children" := childrenDecoder)
>
> childrenDecoder : Decoder Children
> childrenDecoder =
>   ???
>
> The childrenDecoder was what I couldn't figure out. The closest I came was:
>
> childrenDecoder : Decoder Children
> childrenDecoder =
>   customDecoder
>     (Json.list nodeDecoder)
>     (\children -> Result.Ok <| Children children)
>
> But this resulted in the decoder erroring out because there were undefined 
> decoders in the chain. I think it's probably because I don't really 
> understand customDecoder. If anyone can shed light on this second way, I'd 
> appreciate learning about it. Thanks!
>
> Wil
>
>
>
> On Wednesday, October 5, 2016 at 11:42:22 AM UTC-7, Janis Voigtländer 
> wrote:
>>
>>
>> 2016-10-05 20:38 GMT+02:00 Wil Chung <[email protected]>:
>>
>>> I feel like I'm not getting exactly what to do in the case of a 
>>> recursive model.
>>>
>>
>> This is what you are to do in that case: 
>> http://package.elm-lang.org/packages/elm-community/json-extra/1.1.0/Json-Decode-Extra#lazy
>>  
>>
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to