Closed machaval closed 2 years ago
We need to think how it'll handle functions with multiple type parameters, a few options:
fun 2List<T, Q>(a: T, b: Q): Array<T | Q> = [a, b]
you can either write 2List(1, "a")
or 2List<Number, "a">(1, "a")
2List<Number>(1, "a")
and 2List<>(1, "a")
Also, with this in mind, do we want to statically verify that the number of arguments is the correct one? If so, we may need to introduce the parameters into the type of the functions (maybe we have this now, but also make it explicit). For example, maybe a function needs to take a parametric function:
fun f<Q, R>(g: <T>(T) -> T, a: Q, b: R): {a: Q, b: R} = {a: g(a), b: g(b)}
Notice that this is different to:
fun f<Q, R, T>(g: (T) -> T, a: Q, b: R): {a: Q, b: R} = {a: g(a), b: g(b)}
Since in the second case (I think, maybe worth discussing) T must be equal to Q and R.
Following the syntax for function application and definition, I'd say a good syntax for parametric functions types is
<ParameterBinding*>?(Params*) -> Type
Maybe this is out of the scope of the proposal but in the example defaultValue
I would make easier the most common case, that the type String is inferred when the returning type is a lambda (avoiding literals because probably you want a lambda to be called from different values), and I would specify defaultValue<"404" | "505">
if I want to take into account literals (inferring one literal for a lambda doesn't seem useful, that could be replaced for a constant of the lambda's output)
@TomoDC I don't think inferring literals is wrong. For example you may want to do defaultValue("GET")(a.method)
where a.method
returns Null|HttpMethod
and HttpMethod = "GET"|"POST"|...
We may discuss what should be the default behaviour of the solver, but we still are going to find scenarios where we want one or the other and I think that having a way to specify solves any problem and makes it explicit
@teofr
We need to think how it'll handle functions with multiple type parameters, a few options:
All or nothing, if you have something like
fun 2List<T, Q>(a: T, b: Q): Array<T | Q> = [a, b]
you can either write
2List(1, "a")
or2List<Number, "a">(1, "a")
less or equal, with the above example, you can also write
2List<Number>(1, "a")
and2List<>(1, "a")
In my head the idea was to check that either all the Type Parameters are specified or non, so non of this sintax are going to be correct.
Just 2List(1, "a")
or 2List<Number, "a">(1, "a")
Also, with this in mind, do we want to statically verify that the number of arguments is the correct one? If so, we may need to introduce the parameters into the type of the functions (maybe we have this now, but also make it explicit). For example, maybe a function needs to take a parametric function:
fun f<Q, R>(g:
(T) -> T, a: Q, b: R): {a: Q, b: R} = {a: g(a), b: g(b)}
For me having type parameters declared inside a type makes noice on the visibility of that type
For example here the result of g(a)
{a: g(a), b: g(b)}
^^^^
T
Is T
but is not accessible inside the body as T was declared for the type only. And we make the scope global then why do we want to declare it here.
Notice that this is different to:
fun f<Q, R, T>(g: (T) -> T, a: Q, b: R): {a: Q, b: R} = {a: g(a), b: g(b)} Since in the second case (I think, maybe worth discussing) T must be equal to Q and R.
Following the syntax for function application and definition, I'd say a good syntax for parametric functions types is <ParameterBinding>?(Params) -> Type
One thing that we need to discuss is an example like
fun test<T,Q>(a: T): (Q) -> T
In here we are requesting the developer to bind both parameters, and maybe the type of Q
is yet not know. Then for me in this scenario needs to bind it to a new type parameter visible in the callsite.
I think we should at least have a decision on how function types with parametric types should be expressed, even if not implemented at first. For instance, if you want to validate that fun f<T <: String>(a: T): T = a
is applied to a subtype of String
, and then you have a call like f<Number>(2)
, I think the error message should match the error with the incompatibility between the call site and the function definition, and that's easier to make if we can say that f
has type <T <: String>(T) -> T
Regarding fun test<T,Q>(a: T): (Q) -> T
, I agree that if you want to use Q
as another type parameter you can bind it to another parameter available on the call site, so you can make something like
fun test2<R>(a: R) -> Number = test<Number, R>(33)
But I still think this could bring problems, for example, if instead of 33
you use a random number generator.
Git2Gus App is installed but the
.git2gus/config.json
doesn't exist.