Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for algebraic sum types #6

Open
liminalisht opened this issue Apr 7, 2016 · 6 comments
Open

Support for algebraic sum types #6

liminalisht opened this issue Apr 7, 2016 · 6 comments

Comments

@liminalisht
Copy link

I raised this issue a couple days ago with @mattjbray on his servant-elm package, and he directed me here, since servant-elm uses a fork of elm-export under the hood.

Basically, I'd love to see support for algebraic sum types in elm-export. I'd like to be able to get an ElmType instance for something like data Position = Beginning | Middle | End deriving (Eq, Generic)

As an aside, your presentation on Elm at Red Badger was what convinced me to give Elm a go, so thanks for that!

@krisajenkins
Copy link
Owner

I've had a quick look at this. For your example Position type, generating type source (with toElmTypeSource) basically works already. (I've just pushed a whitespace change & a unit test, but that's it.)

There are two problems though, and they both crop up if we give Middle a parameter:

data Position = Beginning | Middle Int | End

The first problem is the Elm type source isn't generated correctly in this case. Shouldn't be hard to fix, but it needs doing.

The second, and more thorny, is the encoding/decoding issue it reveals. Take a look at this code:

import Data.Aeson

data Position
  = Beginning
  | Middle
  | Ending
  deriving (Generic,ElmType,ToJSON)

v1 = encode $ fromList [("pos" :: Text,Beginning)]

data Place
  = Start
  | Inside Int
  | Stop
  deriving (Generic,ElmType,ToJSON)

v2 = encode $ fromList [("pos" :: Text,Start)]

These types are basically identical, except one of them has a constructor with a parameter. I would have expected these two things to encode the same basic thing, but they don't:

λ> v1
"{\"pos\":\"Beginning\"}"
λ> v2
"{\"pos\":{\"tag\":\"Start\",\"contents\":[]}}"

Aeson encodes them differently, even though neither of these constructors has a parameter. That's...a pain. That's going to need some work.

So, in short, yes, I'd like this feature too. A little of it works, but it needs some design thought to get the rest working.

(Glad you like the presentation by the way. Come along to one of our Elm meetups and say hi! http://www.meetup.com/Elm-London-Meetup/)

@liminalisht
Copy link
Author

Ok, thanks for taking a look at this, and for your prompt response. I'll try to take a deeper look at this myself.

@louy2
Copy link

louy2 commented Sep 22, 2016

Ref: haskell/aeson#267

@krisajenkins
Copy link
Owner

After a design discussion with @mattjbray, we now have a plan for how to handle this cleanly. I'm going to need it myself very soon, so hopefully I'll get time to implement it...next week?

@jb55
Copy link

jb55 commented Dec 7, 2016

@krisajenkins did you end up working on this? I might take a stab at it if not.

@FPtje
Copy link

FPtje commented Feb 12, 2017

I've started work on this in a fork. So far I've got encoding. I've aimed for compatibility with Aeson, which is somewhat annoying because of the stuff mentioned above (and more of it).

Here are the PositionEncoder and TimingEncoder test cases.

Some notes:

  • (Json.Encode.float) y0 has parentheses. It's kind of ugly, but they're necessary in some cases, particularly for more complicated types than float.
  • I haven't tested the actual Elm code nor its compatibility with aeson yet.
  • The different ways there are to encode different kinds of sum types complicate the code. I'm not super happy with how I've dealt with this complexity thus far. Input is welcome.
  • The decoder is the next step

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants