Remix.run Logo
Twey 6 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.

the_unproven an hour ago | parent [-]

`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:

  fun map[Self: Functor, A, B](self: Self[A], f: A -> B) -> Self[B];
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!

wavemode 35 minutes ago | parent [-]

How do you define a trait that is itself generic? Like:

    trait ConvertTo[T]:
      fun convert(self) -> T;
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.