This repository was archived by the owner on Nov 1, 2021. It is now read-only.
Subtyping Experiment#23
Merged
chenglou merged 28 commits intoreasonml-community:masterfrom Feb 24, 2017
glennsl:subtyping
Merged
Subtyping Experiment#23chenglou merged 28 commits intoreasonml-community:masterfrom glennsl:subtyping
chenglou merged 28 commits intoreasonml-community:masterfrom
glennsl:subtyping
Conversation
the esy branch is the sandboxed one
This reverts commit 38de449.
We're tracking master and the output (and thus tests) get thrashed every time the version changes. See #17
* Removed Style module, added CssStyleDeclaration * Fixed signature of a few CssStyleDeclaration functions * Added a few ofNode and ofElement functions * Removed Style module, added CssStyleDeclaration * Fixed signature of a few CssStyleDeclaration functions * Added a few ofNode and ofElement functions * Fixed Promise.make * Added reject argument to Promise.make * Fleshed out Promise * Removed a few semi-colons that were troubling webpack * Added CSS2Properties + parentRule to CssStyleDeclaration
* Removed Style module, added CssStyleDeclaration * Fixed signature of a few CssStyleDeclaration functions * Added a few ofNode and ofElement functions * Removed Style module, added CssStyleDeclaration * Fixed signature of a few CssStyleDeclaration functions * Added a few ofNode and ofElement functions * Fixed Promise.make * Added reject argument to Promise.make * Fleshed out Promise * Removed a few semi-colons that were troubling webpack * Fleshed out an experimental fetch implementation
inheritance between them.
* Removed Style module, added CssStyleDeclaration * Fixed signature of a few CssStyleDeclaration functions * Added a few ofNode and ofElement functions * Removed Style module, added CssStyleDeclaration * Fixed signature of a few CssStyleDeclaration functions * Added a few ofNode and ofElement functions * Fixed Promise.make * Added reject argument to Promise.make * Fleshed out Promise * Removed a few semi-colons that were troubling webpack * Fleshed out an experimental fetch implementation
inheritance between them.
…into maybe-functors
Member
Author
|
I also have an example mini-implementation here: https://github.com/glennsl/subtyping-experiment/blob/master/src/main.re |
tekknolagi
reviewed
Feb 24, 2017
|
|
||
| let unwrapUnsafely = fun | ||
| | Some v => v | ||
| | None => assert false; |
Collaborator
There was a problem hiding this comment.
@tekknolagi good point. @glennsl can you provide a message here please? assert false should only ever be used in branches that really can't be reached. Invalid_argument is much better
Also, something something GADT lol
Member
Author
There was a problem hiding this comment.
I've been thinking of having functions like HtmlDivElement.create to avoid the casting and option, but maybe a GADT would be better.... Could then perhaps be used with getElementsByTagName and such too... I'll have to do some reading.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This depends on #15, which isn't strictly necessary, but still very nice to have due to lack of "multiple inheritance"
The relveant commit is this: 025c25f
And the real magic is here: https://github.com/BuckleTypes/reason-js/pull/23/files#diff-f21fba065742f68ab32c1fe347b823b9R14
So what does this do?
In short, it makes e.g.
elementa subtype ofnode. Well, technically a subtype ofnode_like, of whichnodeis also a subtype. But this makes it possible for a function to accept all kinds ofnode_likes,element,node,documentwhatever, as long as its type is constructed accordingly, which meansElement.asNodeand such are now obsolete.So something like this:
Becomes simply:
Which might not look like much, but situations like this comes up surprisingly often.
But how?
By the power of chained phantom types!
So a phantom type is a type (or maybe type parameter, instructions have been unclear) which isn't used for anything other than to differentiate between different kinds of a type. E.g.:
To implement subtyping, we need a "tag" for each kind of object we have, and for both technical (type generalization) and convenience reasons, we will separate the concept of inheritability from the concrete types. So if we want to specify
elementas a subtype ofnode, we would tneed anode_tagand anelement_tag, as well as anode_like 'a. We can then definenodeandelementin terms of these:That's one step, and to also make
elementinheritable, we just add a type parameter toelement_tagand anelement_like 'atype and chain them:In this example I've also used
unitas a kind of short-hand terminator to avoid having to define yet more types just for that.Awesome, but there are downsides, right?
No! Well, maybe, depending on how much you love "informative type errors". There's also some limitations:
"Multiple inheritance" (for lack of a better word) is not supported (Although I think it's technically possible, the ordered nature of type parameters would make it very messy). Lots of dom objects are implement multiple interfaces, e.g.
ElementandDocumentimplement bothNodeandEventTarget. So one has to be picked as the "super-type", in both these casesNodeis a natural pick, andEventTargetwill have to be converted to. With implementation inheritance this is fortunately less of an issue.Type errors are more verbose. E.g.:
They're very informative, containing all the information you need to figure it out, but might seem a bit scary due to its verbosity and formatting (which is also partly because types are printed with ML-formatting).
Other notes
Node.*functions onnode_likes, you'll have to use the module that's appropriate for the type you have. E.g. forelementinstead ofNode.innerTextuseElement.innerText. There shouldn't be any issues with having the implementation inheritance respect subtyping, I'm just not sure it should. I'm not even sure there should be any implementation inheritance at all with subtyping.