Comment by Twey
9 hours ago
Love to see a real-world example of GRIN!
trait Functor[A]:
fun map[B](self, f: A -> B) -> Self[B];
This looks a little wacky to me. I see that you can write HKTs in their η-long form and refer to them unapplied (`Functor`). But I don't understand how I would use this syntax to attach something to the trait that _doesn't_ depend on `A`. For (a silly) example,
trait SizedFunctor[A]: Functor[A]:
type Size;
fun size(self) -> Size;
How do I know that `List[A]::Size` is the same type as `List[B]::Size`?
Relatedly, I want to read `Self` in there as ‘the thing that implements `Functor[A]`’ (e.g. List[A]`), but that makes `Self[B]`, instantiated, mean `List[A][B]`, which I think should be a kind error.
`Self` isn't the applied type (`List[A]`), rather it's the type constructor of kind `* -> *` constrained by `Functor`. In the map example it gets desugared into:
Since `Self` is the unapplied constructor, `Self[B]` just means `Functor[B]` e.g. `List[B]` not `List[A][B]`.
The example you've shown with `SizedFunctor` is not currently supported, as support for associated types is not yet implemented. I got it on the roadmap tho!
How do you define a trait that is itself generic? Like:
Seems to create a single trait ConvertTo, for a generic type with a [T] argument, rather than allowing one to define separate implementations for ConvertTo[i32], ConvertTo[String], etc.