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

Feature Request: Type Aliases in Port Signatures #493

Closed
maxsnew opened this Issue Feb 7, 2014 · 14 comments

Comments

Projects
None yet
5 participants
@maxsnew
Contributor

maxsnew commented Feb 7, 2014

This is explicitly stated as "not implemented (yet)" when you try it, so I'm opening an issue to keep track of progress on this feature.

This is a very desirable property, especially since you might be sending large record types over ports.

Is there a big reason why this isn't currently supported? Will it require changing some internals so that the unaliased type can be recovered (I haven't looked at it myself)?

@johnpmayer

This comment has been minimized.

Contributor

johnpmayer commented Feb 7, 2014

It's not currently supported because the port (de)serialization code is
based on a source-syntax type. I'd guess that was the easiest way to get it
up and running faster. Take a look at the type of the first argument of the
functions inc (
https://github.com/evancz/Elm/blob/master/compiler/Generate/JavaScript/Ports.hs#L33)
and out (
https://github.com/evancz/Elm/blob/master/compiler/Generate/JavaScript/Ports.hs#L84).
It's using SourceSyntax.Type.Type (
https://github.com/evancz/Elm/blob/master/compiler/SourceSyntax/Type.hs#L11
).

The problem is that source syntax only knows that something is a type
constructor, but not if it's an alias or an ADT. This is exactly the
limitation that the other ADT port issue runs into. So basically we need to
re-architect this file so that it uses something smarter, a canonicalized
typerep, rather than a type annotation. We want the generation of port and
json code to be polytypic; see
http://www.cs.ox.ac.uk/jeremy.gibbons/publications/dgp.pdf.

polytypism, that is, parametrization by the shape of data structures
rather than their contents.

On Thu, Feb 6, 2014 at 10:22 PM, Max S. New notifications@github.comwrote:

This is explicitly stated as "not implemented (yet)" when you try it, so
I'm opening an issue to keep track of progress on this feature.

This is a very desirable property, especially since you might be sending
large record types over ports.

Is there a big reason why this isn't currently supported? Will it require
changing some internals so that the unaliased type can be recovered (I
haven't looked at it myself)?

Reply to this email directly or view it on GitHubhttps://github.com//issues/493
.

@johnpmayer

This comment has been minimized.

Contributor

johnpmayer commented Feb 7, 2014

@evancz is there anything currently in the compiler that represents the shape of data? This is analogous to the functionality which Haskell's Generics supplies, but of course wouldn't be exposed as a user library.

@evancz

This comment has been minimized.

Member

evancz commented Feb 8, 2014

This is not supported because it needed pretty large and risky changes. I wanted to get ports released, so I chose to delay this until later.

Essentially, canonicalization does not dealias types. Dealiasing currently happens in the type inferencer and does not modify the types in the AST. I don't actually know if this is essential or not (probably not), but I did not want to deal with this kind of problem at the time.

I have been thinking more about opening up the whole compiler for making tools and about how to enrich the AST in nice ways throughout the pipeline. I think fixing this issue is a really good deliverable that could help guide the larger project in a good direction.

@johnpmayer, I don't know what you mean by "shape". I suspect that means it is not easily available.

@johnpmayer

This comment has been minimized.

Contributor

johnpmayer commented Feb 8, 2014

Ok. Regarding "shape". Say I have a data Foo = Bar Int | Baz String | Qux
Float. The shape of a type is the information about its constructors.
(Really this comment belonged in the ADT thread).

On Sat, Feb 8, 2014 at 10:08 AM, Evan Czaplicki notifications@github.comwrote:

This is not supported because it needed pretty large and risky changes. I
wanted to get ports released, so I chose to delay this until later.

Essentially, canonicalization does not dealias types. Dealiasing currently
happens in the type inferencer, and I don't actually know if this is
essential or not. I did not want to deal with this kind of problem at the
time.

I have been thinking more about opening up the whole compiler for making
tools and about how to enrich the AST in nice ways throughout the pipeline.
I think fixing this issue is a really good deliverable that could help
guide the larger project in a good direction.

@johnpmayer https://github.com/johnpmayer, I don't know what you mean
by "shape". I suspect that means it is not easily available.

Reply to this email directly or view it on GitHubhttps://github.com//issues/493#issuecomment-34546109
.

@evancz evancz added the enhancement label Feb 10, 2014

@maxsnew

This comment has been minimized.

Contributor

maxsnew commented Apr 1, 2014

@evancz I think a good way to resolve this is for the Type Inference/Checking algorithm to output a fully type-annotated AST, which is sort of the current "best practice" for typed functional language compilers. Then any analyses and compilation steps will have all types available to them.

A further step would be making polymorphism explicit in the intermediate language (though later erased at JS codegen). The AST would then be basically a fully annotated System F + Row Polymorphism. I think this would beget a separate AST from the SourceSyntax.

So the process would be:
Parse -> TypeCheck/Annotate SourceSyntax -> Desugar to System F_rows -> Optimize -> Code Gen

@evancz

This comment has been minimized.

Member

evancz commented Apr 1, 2014

I'm planning to do this, but not necessarily because it'll resolve this issue. Part of switching to the Annotated data structure in the AST was so that it made more sense to add types to every expression. The goal here was to get the "type hint" feature on arbitrary values in an Elm program.

When you say go to System F, does this just mean a very explicit set of types where you actually do the forall and exists? I only know that Haskell uses this approach and that it is part of why their record system is so bad. In the decade of proposals, everyone was limited by the fact that they needed to map onto System F to keep all of the optimizations in tact.

Anyway, fixing this particular issue is not as complicated as getting all that done. I think we just need to extend the Canonicalize step to act on declarations or something like that.

@evancz

This comment has been minimized.

Member

evancz commented Apr 1, 2014

Can we create another milestone for all the port related improvements?

@evancz evancz added this to the Ports milestone Apr 1, 2014

@evancz

This comment has been minimized.

Member

evancz commented Apr 1, 2014

@maxsnew

This comment has been minimized.

Contributor

maxsnew commented Apr 1, 2014

I did mean making forall and exists explicit, but I said System F + Row Polymorphism so records would be in the core language. Is the limitation in Haskell just that they're not willing to extend the core language? That doesn't seem relevant since we would be starting with a core language that fits elm and not trying to add records after the fact.

@thSoft

This comment has been minimized.

Contributor

thSoft commented May 1, 2014

+1

@evancz

This comment has been minimized.

Member

evancz commented Jun 12, 2014

Oh shit, it looks like this is fixed in the canonicalize branch! Loving the canonicalize branch right now :)

Can someone confirm this one? If my testing is correct, that means we need to change the error message to remove the "not implemented yet" message.

@mgold

This comment has been minimized.

Contributor

mgold commented Jun 12, 2014

Seems to work for me. Great to have this working.

@evancz evancz closed this Jun 13, 2014

@maxsnew

This comment has been minimized.

Contributor

maxsnew commented Jul 18, 2014

I'm just getting to this and it works for simple types like Bool, String and Int but it doesn't work for things like Maybe String, which is one of my 2 use cases. Ports examples are complicated so I don't want to make a full example if I don't need to, but basically I have a type alias

type Responses = Maybe String

and an incoming port

port responses : Signal Responses

and I get the error


/home/mnew/code/elm/libs/IO/Test.js:8303
      reportAnyErrors = function() { throw e; }
                                           ^
Error: Initialization Error on port 'responses': 
$Maybe is not defined
    at Object.portIn (/home/mnew/code/elm/libs/IO/Test.js:1394:19)
    at Object.Elm.Main.make (/home/mnew/code/elm/libs/IO/Test.js:9378:34)
    at init (/home/mnew/code/elm/libs/IO/Test.js:8298:23)
    at Object.Elm.worker (/home/mnew/code/elm/libs/IO/Test.js:8235:12)
    at /home/mnew/code/elm/libs/IO/Test.js:10033:22
    at callback (/home/mnew/code/elm/libs/IO/Test.js:10073:3)
    at /home/mnew/code/elm/libs/IO/node_modules/jsdom/lib/jsdom.js:255:9
    at process._tickCallback (node.js:419:13)
@evancz

This comment has been minimized.

Member

evancz commented Jul 18, 2014

Lets open a new issue for this. I think Maybe will be broken, but records and all other types should be fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment