I vote (2), fairly strongly
Remember this comment from Vlad:
@phadej For what it's worth, this was my initial thinking when I put ktype
there, so past me agrees with you. What changed my opinion is that two years later (i.e. now) I looked at the examples like fn (type Int -> [a])
and had to double check the specification if it was supposed to be fn ((type Int) -> [a])
or fn (type (Int -> [a]))
.
The point is that the `type` namespace changer can appear deep within a type. It's not like "@"! For exmaple
fn ((type K) -> [a])
makes perfect sense. fn has a required type argument, but in the (type K) sub-part of the type do we switch to the type namespace. (Maybe K is in scope also as a data constructor.) Without the parens, do you really want to wonder about how this parses?
fn (type K -> [a])
I
prefer code that is slightly longer, but much clearer, than saving two
characters but requiring reference to the user manual to parse.
Let's make it simple and unambiguous for now. If it seems painful in practice we can debate liberalising it.
Simon
_______________________________________________