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

Smart generators #1

Open
gampleman opened this issue Jan 4, 2021 · 6 comments
Open

Smart generators #1

gampleman opened this issue Jan 4, 2021 · 6 comments

Comments

@gampleman
Copy link

So here is an idea for a tooling project, I hope it is appropriate:

Problem

It a common design pattern in Elm that we make a type and then need to add "capabilities" to that type. Usually these are forms of integration with various packages. Some common examples include:

  • JSON decoders and encoders
  • Random generators
  • Fuzzers
  • Form builders
  • HTML views

Most programming languages support this by either meta programming (or macros, deriving, template Haskell, etc) or introspection and dynamic dispatch (interfaces/protocols with default implementations).

Elm doesn't support those forms of abstraction instead preferring manual implementation and duplication of these tasks. This has the benefit of allowing more control and customisability of the process, but forces programmers to type out more "boilerplate" code.

A solution

Code generation. However, I think the code generation has to be rather smart for this to work nicely. First of all, it should be type driven. I envisage the user writing the type in a module and then getting a completion suggestion in their editor:

⚡ Generate JSON encoder...
⚡ Generate Fuzzer...

etc.

The generator needs to be able to traverse the type and for each subtype* encountered:

  1. If is a primitive type (primitive types are types that the package provides that need no further expansion) and expand to a call to the appropriate function from that package (generating the appropriate imports if necessary).
  2. If it a type that is local to the module, then recurse for its subtypes.
  3. If it is a type imported from another module, look for a function with an appropriate signature (i.e. when generating a decoder for Color, look for a value with type Json.Decode.Decoder Color:
    • If found just one, import it and generate a call as apropriate.
    • If found multiple, generate a Debug.todo listing the candidates and instructing the user to pick.
    • If none found, generate a Debug.todo with a message instructing the user to implement that.
  4. Generate a call to an appropriate composition operator for all the encountered subtypes.

If anything goes wrong, generate a Debug.todo with a message explaining the problem.

However, since the set of packages that could benefit from this is unbounded, I suggest that each package can contain a script in some well known location that details how this process works for it. Then the extension would search through the packages that are dependencies of the current project and load these as completion items.

Technical challenges

Since this whole process is based around types, there needs to be solid type resolution facilities. For example if the package considers Color a primitive type, than it needs to be ensured that we are taking about the same Color (i.e. for example that this is the color from avh4/elm-color rather than from some other package).

Second, loading scripts from packages into the editor environment has some security, stability and performance implications. Having correct handling around these is a bit tricky.


* By subtype I mean any type encountered in the type declaration:

So for

type Foo 
    = Bar Int
     | Baz { hello = Qumox }

Int and Qumox are subtypes.

@razzeee
Copy link
Member

razzeee commented Jan 4, 2021

Is https://github.com/FranzSkuffka/elm-coder-generator relevant here?

@gampleman
Copy link
Author

Yeah there have been similar tools over the years. I think this idea has two novel aspects to it:

  1. Living in the editor rather than as separate tooling. I think this important since often its easier to just bang out the decoder (or whatever) than go look for that tool you vaguely remember existing, figuring out how to use it, etc.
  2. Letting package authors support it directly, so over time your editor gains more abilities with each dependency.

@razzeee
Copy link
Member

razzeee commented Jan 5, 2021

Agreed, just collecting additional points of data.

Looking at the template:
What's needed: Typescript (for the language server)

Would you be able to mentor this?

@gampleman
Copy link
Author

Probably not as I have no relevant experience and I am unfortunately over committed as is.

@razzeee
Copy link
Member

razzeee commented Jan 5, 2021

Okay, we might still have to consult you at some point

@pierrebeitz
Copy link

pierrebeitz commented Mar 17, 2021

i think https://github.com/kirchner/elm-type-directed-autocomplete could also be relevant here.

/cc @kirchner

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

3 participants