-
Notifications
You must be signed in to change notification settings - Fork 430
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
Unify GADT syntax #555
Comments
One possibility, borrowing from With type something =
| Constructor: (int, int) => this
| Another: (list int) => this; Closer to the current style: type something =
| Constructor (int, int): this
| Another (list int): this; and type something 'a =
| Constructor (int, int): this int
| Another (list int): this unit; Potential advantages are that this syntax might be intuitive to someone who has already used |
I like that idea. It needn't be something restricted merely to GADT syntax unification, you could probably also use it in recursive type declarations, couldn't you? type list 'a =
| []
| Const 'a (this 'a); I just realized that the one major downside to unifying GADT syntax is that things get really verbose when you have many type parameters and aren't making use of GADTs. type myType 'a 'b 'c =
| C1 : this 'a 'b 'c
| C2 : this 'a 'b 'c; Maybe you could then, instead have |
In OCaml, there's a way to alias shortcuts in type definitions using type myType 'a 'b = | C ('a, 'b) : 'this
constraint 'this = myType 'a 'b;
However, having a |
Sure, I don't see why not.
Good point.
That seems like a pretty good choice to me. Another option could be to use ellipses if there's some other reason that just plain type myType 'a 'b 'c =
| C1 : this …
| C2 : this …; or without type myType 'a 'b 'c =
| C1 : myType …
| C2 : myType …; |
Personally, I don't like the idea of making ADT syntax more verbose just to make it more consistent with GADTs. IMHO, conciseness is a major OCaml feature. But yes, I totally agree about GADTs syntax. It is hardly consistent with other parts. I would just consider a concrete example: ADT type expr =
| SDefaultInt
| SDefaultBool
| SDefaultString
| SInt of int
| SBool of bool
| SString of string
let str = function
| SDefaultInt -> "42"
| SDefaultBool -> "true"
| SDefaultString -> "foo"
| SInt n -> string_of_int n
| SBool b -> string_of_bool b
| SString s -> s A sum type constructor may have zero or more type parameters specified immediately after GADT type _ expr =
| DefaultInt : int expr
| DefaultBool : bool expr
| DefaultString : string expr
| Int : int -> int expr
| Bool : bool -> bool expr
| String : string -> string expr
let value : type a. a expr -> a = function
| DefaultInt -> 42
| DefaultBool -> true
| DefaultString -> "foo"
| Int n -> n
| Bool b -> b
| String s -> s A GADT's constructor may have zero or more type parameters specified immediately after colon. Return type should be always specified after To make it more consistent, I would keep ADT syntax as is, but change GADT syntax to: type _ expr =
| DefaultInt => int expr
| DefaultBool => bool expr
| DefaultString => string expr
| Int of int => int expr
| Bool of bool => bool expr
| String of string => string expr It looks like a natural extension of regular sum type to me. |
One thought about arrows before GADT types: Suppose we create an extension (ppx or compiler pull request) to implement type constructors as functions. I feel in that case, we would want the arrows to designate the return type, and yet they would already be used in cases where the constructors were not functions. It might be wise to reserve that arrow for the day when type constructors are functions. |
@jordwalke hmm... arrows already designate the return type of GADT constructor in proposed syntax. How can introducing first class constructor functions affect this? I guess ppx_variants_conv would just generate something like: let default_int : int expr
let default_bool : bool expr
let default_string : string expr
let int : int => int expr
let bool : bool => bool expr
let string : string => string expr |
You could argue that this is not true because arrows don't describe the "return type" of GADT constructors if they're not truly functions - they don't "return" anything. What if you wanted to distinguish between constructors that are functions (via some ppx extension etc) and ones that aren't? The ones that are indeed functions would have "return types" and I think arrows would be appropriate. When there also exists constructors which are not first class functions, you'd probably expect that there be no arrow to describe their type. At least those are my current thoughts on it. |
I second @artemkin opinion that it is a bad thing to make the declaration of sum types more verbose to make GADT's look less odd. I do not understand how this syntax improves the consistency: type _ expr =
| DefaultInt => int expr
| DefaultBool => bool expr
| DefaultString => string expr
| Int of int => int expr
| Bool of bool => bool expr
| String of string => string expr In upstream OCaml, the |
@michipili I meant inconsistency of To convert ADT to GADT, you would need to replace
It can be treated as a zero arity function, so it depends on the point of view)) Anyway, you can always use unary constructor with a parameter of unit type: | SomeString of unit => string expr |
@artemkin I see, thank you for the clarification! An inconvenient of the
This is consistent with usual type annotations introduced by
is a bit awkward, esp. since the concurrent way
does not mention the Does it seem doable (and desirable?) to change the former to I do not want to let this thread drift too far away but it seems natural to discuss the syntax of functions using some types with the syntax of the definition of thee types. |
@michipili I like the idea of using |
See the discussion here: #491 (comment)
We can make GADTs less scary, by making them a natural syntactic extension of regular variant declarations.
One proposal is as follows, but is more verbose, so if you have better ideas, please discuss here:
If regular variant definitions were as follows:
Then creating a GADT is not such a huge step, and the syntax helps to explain what GADTs are in the first place.
The only problem is that (as the first example shows), in the case of regular variant definitions, there is a lot of redundancy. I'm hoping someone has a good proposed solution for this.
The text was updated successfully, but these errors were encountered: