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.
