Closed ghost closed 9 years ago
Currently the fat arrow has a very clear semantic: it means that the thing on the left is evaluated lazily. That's even true for a type function!
This proposal would break that, since in a function type nothing is evaluated lazily.
Note that it's also inconsistent with the traditional C syntactic principle: "declaration follows use". In C, an array type is written int[][]
not [][]=>int
. And I think the second option would be a really ugly way to write array types (though I note that Go sorta goes down this path).
Why not make the type function thingies similar to the current Callable
syntax, then?
Foo bar<Baz>(Qux q) => nothing;
Foo(Qux)<Baz> bar2 = bar;
@Zambonifofex the syntax Foo(Qux)<Baz>
looks to me like a type of a type function, not a definition of a type function.
That isn't wrong. Both bar
and bar2
are type functions and have the same type, but bar2
is declared like an value, instead of like an function. Foo(Qux)<Bar>
is the type of both.
Nope, that's not the right way to look at it. That's like not seeing the difference between (Float x) => x
and Float(Float)
.
A type function is really a function. Thus, we write it as <T> => T
, using a similar syntax we use to write value functions.
Well, I'm confused. I have thought about this, and came to the conclusion that <Foo> => Bar
means two different things.
Foo
), andFoo
.Am I right in thinking like this?
That's right, but you're not thinking meta enough. I'm saying Foo(Qux)<Bar>
looks like the type of a type function at the next meta-level up.
So, you mean:
Foo<Bar> typefun = <Bar> => Baz;
Or, even better:
Foo typefun<Bar> => Baz;
Where Foo
is the type of the type Baz
...
By the way, @gavinking, would it not be better to not have it mean two different things? Maybe have a function that receives a type and "returns" another be represented as <Foo> => Bar
, and the type of a function that receives a type and returns another as Bar<Foo>
...
I don't understand. You've lost me.
Look, I think you're not seeing this because you're writing everything with Foo
, and Bar
as opaque things whereas really Bar
is an expression that involves Foo
. There's just a huge difference there. The thing on the left of the fat arrow is always a parameter list, not a type!
When I have a generic function type like <T> => List<String>(List<T>)
, the stuff to the right of the fat arrow is an expression involving parameters declared on the right of the fat arrow.
If I have a plain function type String(Integer)
, String
simply can't be an expression that involves Integer
. Indeed, Integer
isn't a parameter at all! So what sense would it make to write that as (Integer) => String
?
No, I've realized this. What got me confused was the fact that <Foo> => Bar
means two different things.
What I said is that I think <Foo> => Bar
should be only a type function, and not a type by itself. And, have Foo<Bar>
be the type of a function that receives a type and returns an object. For example:
function foo<Bar>()
given Bar<Baz>
{
// ...
}
foo< <Baz>=>String >(); // Ok
<Baz>=>String err => nothing; // Error
String qux<Bar>() => "Hello";
String()<> quxx = qux; // Ok
Since I don't agree with this thread's suggestion anymore, and am now suggesting something else, I'll close this thread. @gavinking should I open another thread, should I reopen this one, or should I just leave this closed, and don't open anything?
What I said is that I think
<Foo> => Bar
should be only a type function, and not a type by itself
Nononono!
That's like saying: I think (Float x) => x
should be only a function, and not a value. That's the situation in languages without higher-order functions.
Likewise, in a language with higher-order generic types, we have functions that are types.
That's the whole conceptual model. It's not a weird wrinkle of the syntax; it's a correct representation of exactly what is going on here!
For me, this makes more sense than what is done currently:
It also resembles the syntax for type functions, and works nicely with it:
Besides, the parameter lists are in the same order in the type of the function, as they are when calling the function!