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.

Reply via email to