agrafix / elm-bridge

Haskell: Derive Elm types from Haskell types
BSD 3-Clause "New" or "Revised" License
101 stars 27 forks source link

Recursive types #22

Open oliver-batchelor opened 6 years ago

oliver-batchelor commented 6 years ago

Hi there - there's an issue creating Elm decoders for recursive types, apparently Elm cannot handle recursive values due to it's strictness.

jsonDecEdit is defined directly in terms of itself, causing an infinite loop.

Maybe the solution is to give it a dummy argument to a helper function? e.g.


jsonDecEdit_ : () -> Json.Decode.Decoder Edit
jsonDecEdit _ =  -- real decoder goes here

jsonDecEdit : Json.Decode.Decoder Edit
jsonDecEdit = jsonDecEdit_ ()
type Edit  =
    Add Int Object
    | Delete Int
    | Move (List Int) Vec2
    | Multi (List Edit)

jsonDecEdit : Json.Decode.Decoder ( Edit )
jsonDecEdit =
    let jsonDecDictEdit = Dict.fromList
            [ ("Add", Json.Decode.map2 Add (Json.Decode.index 0 (Json.Decode.int)) (Json.Decode.index 1 (jsonDecObject)))
            , ("Delete", Json.Decode.map Delete (Json.Decode.int))
            , ("Move", Json.Decode.map2 Move (Json.Decode.index 0 (Json.Decode.list (Json.Decode.int))) (Json.Decode.index 1 (jsonDecVec2)))
            , ("Multi", Json.Decode.map Multi (Json.Decode.list (jsonDecEdit)))
            ]
    in  decodeSumObjectWithSingleField  "Edit" jsonDecDictEdit
agrafix commented 6 years ago

This alone won't help as we can probably also have mutual recursion. So to fix this we have to add a _-function to all object decoders and always use that instead, or build in recursion detection which I want to avoid.

Other thoughts? cc @bartavelle

Also: Are you up for doing a PR @Saulzar ? :)

oliver-batchelor commented 6 years ago

Would it work if we change the Dict to be a dict of functions () -> Decoder a?

Happy to figure out a PR if the solution works :)

bartavelle commented 6 years ago

@agrafix no other thoughts, except that this helper exists.

agrafix commented 6 years ago

Ah, lazy sounds good!

bartavelle commented 6 years ago

Seems to work well for me right now, any update?

ncaq commented 2 years ago

I wrote quite a lot of IsElmDefinition definitions manually, because this library does not have an option to generate types that are not type aliases, and because I had to define and adapt special dummy types in Haskell for Elm, which cannot handle recursive data types in type aliases. I have written quite a lot of IsElmDefinition definitions manually.

I'm considering modifying it for pull requests because I think it might be better to be able to define types that are not type alias, but is there any commitment to type alias?