Open hyphenrf opened 3 years ago
Thanks for asking. This has been a longstanding issue where we aren't sure what we want. For example:
https://github.com/brownplt/pyret-lang/issues/307 https://groups.google.com/g/pyret-discuss/c/FUb96Hnobuw/m/iH_Vh6UIDFgJ
The weird output in that issue is just a symptom of a few problematic cases that revolve around what guarantees one ought to expect from datatype-ness.
There are two important cases to consider:
Both cases are fairly fraught for datatypes.
The second is bad dynamically because there is a lot of annotation checking that would need to happen to re-bless the value as a member of the datatype after extension. Statically it's a bit easier to check, though if the programmer's intent was to have smart constructors for a datatype that excluded certain constructions, this could allow synthesizing values of that datatype with functional extension that the author of the smart constructor didn't intend.
The first is tricky for a combination of static and dynamic reasons, but mostly static reasons. Statically, the type-checker tracks the Set
datatype including all of its fields and methods, and that's what it means to be a Set
. Once it gets extended, it's some new type, which is Set
plus stuff. We don't have a concrete syntax for that type (in part because expressing that type is not obvious to do). So all the existing code that uses Set
could be made to work with the extensions, but we don't have a way to type-check (or really assign a good dynamic type to) the resulting value.
I think we should probably just make the case you're trying be an error directly rather than letting these Frankenvalues float around. At the moment there's just more design work to do in both cases, and I think until we resolve it this is just a not-so-great corner of the language to play with.
Of course, functional extension is pretty great with plain record types, and we use it all over the place in the compiler. It could also benefit from some type-level concatenation of records (the missing operator for handling the adding-new-fields case), and that's to-be-designed.
I hope that's a useful response – I would be happy to chat more about what needs to happen next here from a design and implementation standpoint to make this work in a more satisfying way.
I've been trying different ways to extend values produced by constructors but I can't seem to make it work.. My latest attempt with a function that should produce a subtype:
produces a match exception instead.