On Wed, Aug 17, 2022 at 11:17 AM Brian Candler <b.cand...@pobox.com> wrote:
> So when I write > > func (e Plus[Evaler]) Eval() int { > > IIUC, it is effectively treated as if it were the following (not currently > valid syntax): > > func (e Plus[Evaler any]) Eval() int { > > - i.e. inside this function "Evaler" is a local type parameter whose name > just happens to shadow the outer type definition, and is not constrained. > > Aha: I think I can see the lack of covariance explicitly if I try to do > this: > > func (e Plus[a]) Eval() int { > ee := any(e).(Plus[Evaler]) > return ee.left.Eval() + ee.right.Eval() > } > // panic: interface conversion: interface {} is main.Plus[main.Expr], not > main.Plus[main.Evaler] > > OK. So whilst I know that e has struct fields 'left' and 'right', because > it's one of the Plus[a] family of types, I don't know anything at compile > time about the types of those fields. But I can assert it at runtime > <https://go.dev/play/p/VAPpx5xxheQ>, and now I have some code that runs, > albeit ugly and without compile-time checks: > > func (e Plus[a]) Eval() int { > return any(e.left).(Evaler).Eval() + any(e.right).(Evaler).Eval() > } > Yes. The benefit is that instead of having the `Eval` method exist and panic if the type argument does not implement `Evaler`, you can have it exist *only* if the type argument implements `Evaler`. That is, the benefit is in the increased type safety that a) you are being more "honest" about what methods `Plus` has, to your caller and b) you are being kept more honest about what methods are available to you, when you write your `Eval` method. > > Aside: I can't see that there's much use for the type parameter 'a', > except if I needed to declare variables of that type: > > func (e Plus[a]) Eval() int { > var left a = e.left > var right a = e.right > return any(left).(Evaler).Eval() + any(right).(Evaler).Eval() > } > > On Wednesday, 17 August 2022 at 09:50:29 UTC+1 axel.wa...@googlemail.com > wrote: > >> On Wed, Aug 17, 2022 at 10:43 AM Brian Candler <b.ca...@pobox.com> wrote: >> >>> That's an interesting paper - at least the early parts that I could >>> understand! >>> >>> I tried converting <https://go.dev/play/p/yJvOncevnoP> their main >>> motivating example from fig 8, but got stuck by not being able to put a >>> method on a parameterised type: >>> >> >>> func (e Plus[a Evaler]) Eval() int { >>> return e.left.Eval() + e.right.Eval() >>> } >>> // ./prog.go:21:16: syntax error: unexpected Evaler, expecting ] >>> >>> func (e Plus[Evaler]) Eval() int { >>> return e.left.Eval() + e.right.Eval() >>> } >>> // ./prog.go:24:16: e.left.Eval undefined (type Evaler has no field or >>> method Eval) >>> // ./prog.go:24:33: e.right.Eval undefined (type Evaler has no field or >>> method Eval) >>> >>> func (e Plus[a]) Eval() int { >>> return e.left.Eval() + e.right.Eval() >>> } >>> // ./prog.go:24:16: e.left.Eval undefined (type a has no field or method >>> Eval) >>> // ./prog.go:24:33: e.right.Eval undefined (type Evaler has no field or >>> method Eval) >>> >>> Is this what is meant by: >>> >>> >>> *Another result is the proposal for covariant receiver typing, a feature >>> required by The Expression Problem. It is not part of the Go team’s current >>> design, but they have noted it is backward compatible and are considering >>> adding it in the future.* >>> >>> ? >>> >> >> Yes, that's what is meant by that. Though the issue is not putting a >> method on a parameterized type - you can do that. And it's not even putting >> a method with extra type parameters on a type - you can't do that and it >> doesn't seem possible under the current design restrictions put on generics >> in Go. >> But to have a method with a receiver more tightly constrained than the >> type itself (personally, I've been calling that "refined method >> constraints", in lieu of a better term). That seems an entirely possible >> future extension. >> But not yet. We should first try out generics as they are for a while. >> >> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to golang-nuts...@googlegroups.com. >>> >> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/528c0c73-e2db-4153-a505-6003deb886f2n%40googlegroups.com >>> <https://groups.google.com/d/msgid/golang-nuts/528c0c73-e2db-4153-a505-6003deb886f2n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/420a41f5-ad94-41a9-969b-e71aa2ab698fn%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/420a41f5-ad94-41a9-969b-e71aa2ab698fn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfEQqLQaS7zLhN6ydvtrxJwfp%2BC73hWT_u7nmSyp7avpww%40mail.gmail.com.