Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-03 Thread Steven Blenkinsop
On Sat, Aug 3, 2019 at 2:11 AM, Ian Lance Taylor  wrote:

> You're right, I wrote it wrong.  Actually I'm not sure how to write that
> contract.  Ideally we want to say that T is either comparable or has the
> Equal(T) bool method, but there is no way to write that.  We can embed
> comparable(T), but we can't do that in a disjunction with Equal(T) bool.


So I guess I was building castles in the sky, then. Though, just allowing
this does seem like a viable option. I would guess that the reason not to
allow disjunction between contracts or between constraints on different
types is so that whether each type satisfies a contract can be decided
without reference to the constraints on any other type. Allowing
disjunction between single-parameter contracts applied to the same type
would preserve this property, and the syntax of using these contracts as
constraints would make the restriction that they have to be applied to the
same type fall naturally out of the syntax. You lose the property that the
constraints for any particular type parameter are already in conjunctive
normal form, but you already need to do normalization to check the
conjunctive normal form against the disjunctive normal form in order to
determine whether one contract allows its parameter to satisfy another
contract (when calling generic code from generic code).

As for the generic contracts I was showing, they would be very useful if
this were allowed, but I can understand the teachability hazard of having
two kinds of type parameters on a single declaration. The draft already has
two kinds of type parameters, since contract parameters are different from
regular type parameters, but as long as you never have both kinds of
parameters in play, people don't necessarily need to understand the
distinction between them.

On Sat, Aug 3, 2019 at 2:11 AM, Ian Lance Taylor  wrote:

> On Fri, Aug 2, 2019 at 9:25 PM Steven Blenkinsop 
> wrote:
> >
> > On Fri, Aug 2, 2019 at 6:55 PM 'Axel Wagner' via golang-nuts <
> golang-nuts@googlegroups.com> wrote:
> >>
> >>
> >> contract Comparable(T) {
> >>   T comparable, Equal(T) bool
> >> }
> >
> >
> > Wait, does this work? I mean, `comparable` is a contract, but it's being
> used as a constraint.
>
> You're right, I wrote it wrong.  Actually I'm not sure how to write
> that contract.  Ideally we want to say that T is either comparable or
> has the Equal(T) bool method, but there is no way to write that.  We
> can embed comparable(T), but we can't do that in a disjunction with
> Equal(T) bool.
>
>
> > The same issue comes up with the
> >
> > switch T.(type) { ... }
> >
> > idea. Even if you're only constraining one type at a time like this, you
> might still need to express a relationship to another type parameter.
> Unless this is allowed:
> >
> > switch (type) {
> > case comparable(T): ...
> > case Equaler(T): ...
> > }
>
> I suspect that switch T.(type) would have to only permit disjunctions
> listed in the contract for T.
>
> Ian
>

-- 
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/CANjmGJsTFyOMFC5i_5UM5Vpb%2Bpfu-YLkAAmNnMRTkhp_jyKMAg%40mail.gmail.com.


Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-03 Thread Ian Lance Taylor
On Fri, Aug 2, 2019 at 9:25 PM Steven Blenkinsop  wrote:
>
> On Fri, Aug 2, 2019 at 6:55 PM 'Axel Wagner' via golang-nuts 
>  wrote:
>>
>>
>> contract Comparable(T) {
>>   T comparable, Equal(T) bool
>> }
>
>
> Wait, does this work? I mean, `comparable` is a contract, but it's being used 
> as a constraint.

You're right, I wrote it wrong.  Actually I'm not sure how to write
that contract.  Ideally we want to say that T is either comparable or
has the Equal(T) bool method, but there is no way to write that.  We
can embed comparable(T), but we can't do that in a disjunction with
Equal(T) bool.


> The same issue comes up with the
>
> switch T.(type) { ... }
>
> idea. Even if you're only constraining one type at a time like this, you 
> might still need to express a relationship to another type parameter. Unless 
> this is allowed:
>
> switch (type) {
> case comparable(T): ...
> case Equaler(T): ...
> }

I suspect that switch T.(type) would have to only permit disjunctions
listed in the contract for T.

Ian

-- 
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/CAOyqgcW79egVQJ1aDe9YpMYEs1E8y3F4yfcFnJQx13Khxyvx2g%40mail.gmail.com.


Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-02 Thread Steven Blenkinsop
On Fri, Aug 2, 2019 at 6:55 PM 'Axel Wagner' via golang-nuts <
golang-nuts@googlegroups.com> wrote:

>
> contract Comparable(T) {
>   T comparable, Equal(T) bool
> }
>

Wait, does this work? I mean, `comparable` is a contract, but it's being
used as a constraint. Could you also write:

contract Equaler(T) {
T Equal(T) bool
}

>
contract Comparable(T) {
T comparable, Equaler
}

? Or is comparable just special? Or does this not actually work, even for
comparable? This would certainly be convenient if you could do it, though
it means contracts involving a single type are privileged over others (you
can create a disjunction between constraints, but not between contracts,
for example). It seems like if you can create contract constraints like
this, you'd also want to be able to make *generic* contract constraints, to
capture things like

contract Appender(type Elem)(T) {
T Append(...Elem) T
}

contract Appendable(type Elem)(T) {
T []Elem, (Appender(Elem)) // Parens to avoid parsing like a method
constraint
}

The same issue comes up with the

switch T.(type) { ... }

idea. Even if you're only constraining one type at a time like this, you
might still need to express a relationship to another type parameter.
Unless this is allowed:

switch (type) {
case comparable(T): ...
case Equaler(T): ...
}

On Fri, Aug 2, 2019 at 6:55 PM 'Axel Wagner' via golang-nuts <
golang-nuts@googlegroups.com> wrote:

> FWIW:
> interface{}(a) == interface{}(b)
> would work. It would panic if a and b have the same, non-comparable type.
> But if you know the type is equal and comparable, it's well-defined and
> does what you want. So you have to modify your code a bit:
>
> type equaler(type T) interface {
>   Equal(T) bool
> }
>
> contract Comparable(T) {
>   T comparable, Equal(T) bool
> }
>
> func Compare(type T Comparable)(a, b T) bool {
>   if eq, ok := a.(equaler(T)); ok {
> return eq.Equal(b)
>   }
>   // Okay, this is weird, but: If you have `func (*T) Equal(T) bool`, a T
> (value) would
>   // be accepted by the contract, as contracts don't distinguish between
> value and
>   // pointer-receivers. But it would fail above type-assertion, as values
> don't include
>   // pointer-methods in their method set.
>   if eq, ok := ().(equaler(T)); ok {
> return eq.Equal(b)
>   }
>   return interface{}(a) == interface{}(b)
> }
>
> I can't think of anything in the current design draft preventing this from
> working (though I'm sure Ian can correct me if I'm wrong).
>
> It's a special case for equality-comparison though, it doesn't generalize
> to any other operators.
>
> On Fri, Aug 2, 2019 at 10:40 PM Bruno Albuquerque  wrote:
>
>> Ok, it makes sense. I do think that supporting something like this might
>> make the proposal even more appealing as it will bring custom types
>> somewhat closer to builtin types by allowing generic functions/methods that
>> can act on both at the same time.
>>
>> On Fri, Aug 2, 2019 at 1:28 PM Ian Lance Taylor  wrote:
>>
>>> On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque  wrote:
>>> >
>>> > I was thinking about a way to  "extend" usual operations (say,
>>> equality checks) to types that can not be compared the usual way (they are
>>> not "comparable" in the contract sense) and came up with something like
>>> this:
>>> >
>>> > // Just to use for type assertion later.
>>> > type Equaler interface {
>>> >   Equal(Equaler) bool
>>> > }
>>> >
>>> > contract Comparable(T) {
>>> >   T comparable(T), Equal(T) bool
>>> > }
>>> >
>>> > func Compare(type T Comparable)(a, b T) bool {
>>> >   if eq, ok := a.(Equaler); ok {
>>> > return eq.Equal(b)
>>> >   }
>>> >
>>> >   return a == b  // Does this work at all?
>>> > }
>>> >
>>> > Would this work? More specifically it looks to me that that if the
>>> specific type is not comparable (But has the Equal method), the compiler
>>> might see the "==" comparison in the function and give an error.
>>> >
>>> > One way around this would possibly be to use something similar to type
>>> assertion (in this case, a and b would have to be asserted to "comparable"
>>> which I guess is not possible as it is a contract). Or, the compiler could
>>> be smart enough to know that if we reached that check, then the type must
>>> be comparable (so it would also not give an error).
>>>
>>> In the current design draft, that would not work.  The == operator is
>>> not supported by all possible types, so it is not permitted.
>>>
>>> We definitely don't want to rely on the compiler being smart enough.
>>> Any such approach would require writing down the exact inference rules
>>> that the compiler is permitted to use.  Otherwise different compilers
>>> would behave differently.
>>>
>>> One possibility we've toyed with is
>>>
>>> switch T.(type) { // Note: switch on type parameter itself, not a
>>> value of that type.
>>> case Equaler:
>>> ...
>>> case comparable:
>>> // Permit using == operator here on values of type 

Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-02 Thread Robert Engels
Clear as mud. 

> On Aug 2, 2019, at 6:03 PM, 'Axel Wagner' via golang-nuts 
>  wrote:
> 
> Just tried running it through the prototype type-checker and one correction: 
> You also have to convert `a` and `` to interface{}, so that you are allowed 
> to type-assert on them:
>   if e, ok := (interface{}(a)).(equaler(T)); ok { return e.Eq(b) } 
>   if e, ok := (interface{}()).(equaler(T)); ok { return e.Eq(b) }
> 
> Anyway, I hope by now the extreme hackishness of this "solution" is clear :)
> 
>> On Sat, Aug 3, 2019 at 12:55 AM Axel Wagner  
>> wrote:
>> FWIW:
>> interface{}(a) == interface{}(b)
>> would work. It would panic if a and b have the same, non-comparable type. 
>> But if you know the type is equal and comparable, it's well-defined and does 
>> what you want. So you have to modify your code a bit:
>> 
>> type equaler(type T) interface {
>>   Equal(T) bool
>> }
>> 
>> contract Comparable(T) {
>>   T comparable, Equal(T) bool
>> }
>> 
>> func Compare(type T Comparable)(a, b T) bool {
>>   if eq, ok := a.(equaler(T)); ok {
>> return eq.Equal(b)
>>   }
>>   // Okay, this is weird, but: If you have `func (*T) Equal(T) bool`, a T 
>> (value) would
>>   // be accepted by the contract, as contracts don't distinguish between 
>> value and
>>   // pointer-receivers. But it would fail above type-assertion, as values 
>> don't include
>>   // pointer-methods in their method set.
>>   if eq, ok := ().(equaler(T)); ok {
>> return eq.Equal(b)
>>   }
>>   return interface{}(a) == interface{}(b)
>> }
>> 
>> I can't think of anything in the current design draft preventing this from 
>> working (though I'm sure Ian can correct me if I'm wrong).
>> 
>> It's a special case for equality-comparison though, it doesn't generalize to 
>> any other operators.
>> 
>>> On Fri, Aug 2, 2019 at 10:40 PM Bruno Albuquerque  wrote:
>>> Ok, it makes sense. I do think that supporting something like this might 
>>> make the proposal even more appealing as it will bring custom types 
>>> somewhat closer to builtin types by allowing generic functions/methods that 
>>> can act on both at the same time.
>>> 
 On Fri, Aug 2, 2019 at 1:28 PM Ian Lance Taylor  wrote:
 On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque  wrote:
 >
 > I was thinking about a way to  "extend" usual operations (say, equality 
 > checks) to types that can not be compared the usual way (they are not 
 > "comparable" in the contract sense) and came up with something like this:
 >
 > // Just to use for type assertion later.
 > type Equaler interface {
 >   Equal(Equaler) bool
 > }
 >
 > contract Comparable(T) {
 >   T comparable(T), Equal(T) bool
 > }
 >
 > func Compare(type T Comparable)(a, b T) bool {
 >   if eq, ok := a.(Equaler); ok {
 > return eq.Equal(b)
 >   }
 >
 >   return a == b  // Does this work at all?
 > }
 >
 > Would this work? More specifically it looks to me that that if the 
 > specific type is not comparable (But has the Equal method), the compiler 
 > might see the "==" comparison in the function and give an error.
 >
 > One way around this would possibly be to use something similar to type 
 > assertion (in this case, a and b would have to be asserted to 
 > "comparable" which I guess is not possible as it is a contract). Or, the 
 > compiler could be smart enough to know that if we reached that check, 
 > then the type must be comparable (so it would also not give an error).
 
 In the current design draft, that would not work.  The == operator is
 not supported by all possible types, so it is not permitted.
 
 We definitely don't want to rely on the compiler being smart enough.
 Any such approach would require writing down the exact inference rules
 that the compiler is permitted to use.  Otherwise different compilers
 would behave differently.
 
 One possibility we've toyed with is
 
 switch T.(type) { // Note: switch on type parameter itself, not a
 value of that type.
 case Equaler:
 ...
 case comparable:
 // Permit using == operator here on values of type T in this case 
 only.
 }
 
 We'll see whether some such facility seems useful.  This is something
 we can add later, if the current design draft seems workable.
 
 Ian
>>> 
>>> -- 
>>> 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/CAEd86Tz4tvx3qPZ4fV86AyV-B8YOXEMZMR-L4f6fcTyAuX_eXQ%40mail.gmail.com.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and 

Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-02 Thread 'Axel Wagner' via golang-nuts
Just tried running it through the prototype type-checker and one
correction: You also have to convert `a` and `` to interface{}, so that
you are allowed to type-assert on them:
  if e, ok := (interface{}(a)).(equaler(T)); ok { return e.Eq(b) }
  if e, ok := (interface{}()).(equaler(T)); ok { return e.Eq(b) }

Anyway, I hope by now the extreme hackishness of this "solution" is clear :)

On Sat, Aug 3, 2019 at 12:55 AM Axel Wagner 
wrote:

> FWIW:
> interface{}(a) == interface{}(b)
> would work. It would panic if a and b have the same, non-comparable type.
> But if you know the type is equal and comparable, it's well-defined and
> does what you want. So you have to modify your code a bit:
>
> type equaler(type T) interface {
>   Equal(T) bool
> }
>
> contract Comparable(T) {
>   T comparable, Equal(T) bool
> }
>
> func Compare(type T Comparable)(a, b T) bool {
>   if eq, ok := a.(equaler(T)); ok {
> return eq.Equal(b)
>   }
>   // Okay, this is weird, but: If you have `func (*T) Equal(T) bool`, a T
> (value) would
>   // be accepted by the contract, as contracts don't distinguish between
> value and
>   // pointer-receivers. But it would fail above type-assertion, as values
> don't include
>   // pointer-methods in their method set.
>   if eq, ok := ().(equaler(T)); ok {
> return eq.Equal(b)
>   }
>   return interface{}(a) == interface{}(b)
> }
>
> I can't think of anything in the current design draft preventing this from
> working (though I'm sure Ian can correct me if I'm wrong).
>
> It's a special case for equality-comparison though, it doesn't generalize
> to any other operators.
>
> On Fri, Aug 2, 2019 at 10:40 PM Bruno Albuquerque  wrote:
>
>> Ok, it makes sense. I do think that supporting something like this might
>> make the proposal even more appealing as it will bring custom types
>> somewhat closer to builtin types by allowing generic functions/methods that
>> can act on both at the same time.
>>
>> On Fri, Aug 2, 2019 at 1:28 PM Ian Lance Taylor  wrote:
>>
>>> On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque  wrote:
>>> >
>>> > I was thinking about a way to  "extend" usual operations (say,
>>> equality checks) to types that can not be compared the usual way (they are
>>> not "comparable" in the contract sense) and came up with something like
>>> this:
>>> >
>>> > // Just to use for type assertion later.
>>> > type Equaler interface {
>>> >   Equal(Equaler) bool
>>> > }
>>> >
>>> > contract Comparable(T) {
>>> >   T comparable(T), Equal(T) bool
>>> > }
>>> >
>>> > func Compare(type T Comparable)(a, b T) bool {
>>> >   if eq, ok := a.(Equaler); ok {
>>> > return eq.Equal(b)
>>> >   }
>>> >
>>> >   return a == b  // Does this work at all?
>>> > }
>>> >
>>> > Would this work? More specifically it looks to me that that if the
>>> specific type is not comparable (But has the Equal method), the compiler
>>> might see the "==" comparison in the function and give an error.
>>> >
>>> > One way around this would possibly be to use something similar to type
>>> assertion (in this case, a and b would have to be asserted to "comparable"
>>> which I guess is not possible as it is a contract). Or, the compiler could
>>> be smart enough to know that if we reached that check, then the type must
>>> be comparable (so it would also not give an error).
>>>
>>> In the current design draft, that would not work.  The == operator is
>>> not supported by all possible types, so it is not permitted.
>>>
>>> We definitely don't want to rely on the compiler being smart enough.
>>> Any such approach would require writing down the exact inference rules
>>> that the compiler is permitted to use.  Otherwise different compilers
>>> would behave differently.
>>>
>>> One possibility we've toyed with is
>>>
>>> switch T.(type) { // Note: switch on type parameter itself, not a
>>> value of that type.
>>> case Equaler:
>>> ...
>>> case comparable:
>>> // Permit using == operator here on values of type T in this
>>> case only.
>>> }
>>>
>>> We'll see whether some such facility seems useful.  This is something
>>> we can add later, if the current design draft seems workable.
>>>
>>> Ian
>>>
>> --
>> 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/CAEd86Tz4tvx3qPZ4fV86AyV-B8YOXEMZMR-L4f6fcTyAuX_eXQ%40mail.gmail.com
>> 
>> .
>>
>

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

Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-02 Thread 'Axel Wagner' via golang-nuts
FWIW:
interface{}(a) == interface{}(b)
would work. It would panic if a and b have the same, non-comparable type.
But if you know the type is equal and comparable, it's well-defined and
does what you want. So you have to modify your code a bit:

type equaler(type T) interface {
  Equal(T) bool
}

contract Comparable(T) {
  T comparable, Equal(T) bool
}

func Compare(type T Comparable)(a, b T) bool {
  if eq, ok := a.(equaler(T)); ok {
return eq.Equal(b)
  }
  // Okay, this is weird, but: If you have `func (*T) Equal(T) bool`, a T
(value) would
  // be accepted by the contract, as contracts don't distinguish between
value and
  // pointer-receivers. But it would fail above type-assertion, as values
don't include
  // pointer-methods in their method set.
  if eq, ok := ().(equaler(T)); ok {
return eq.Equal(b)
  }
  return interface{}(a) == interface{}(b)
}

I can't think of anything in the current design draft preventing this from
working (though I'm sure Ian can correct me if I'm wrong).

It's a special case for equality-comparison though, it doesn't generalize
to any other operators.

On Fri, Aug 2, 2019 at 10:40 PM Bruno Albuquerque  wrote:

> Ok, it makes sense. I do think that supporting something like this might
> make the proposal even more appealing as it will bring custom types
> somewhat closer to builtin types by allowing generic functions/methods that
> can act on both at the same time.
>
> On Fri, Aug 2, 2019 at 1:28 PM Ian Lance Taylor  wrote:
>
>> On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque  wrote:
>> >
>> > I was thinking about a way to  "extend" usual operations (say, equality
>> checks) to types that can not be compared the usual way (they are not
>> "comparable" in the contract sense) and came up with something like this:
>> >
>> > // Just to use for type assertion later.
>> > type Equaler interface {
>> >   Equal(Equaler) bool
>> > }
>> >
>> > contract Comparable(T) {
>> >   T comparable(T), Equal(T) bool
>> > }
>> >
>> > func Compare(type T Comparable)(a, b T) bool {
>> >   if eq, ok := a.(Equaler); ok {
>> > return eq.Equal(b)
>> >   }
>> >
>> >   return a == b  // Does this work at all?
>> > }
>> >
>> > Would this work? More specifically it looks to me that that if the
>> specific type is not comparable (But has the Equal method), the compiler
>> might see the "==" comparison in the function and give an error.
>> >
>> > One way around this would possibly be to use something similar to type
>> assertion (in this case, a and b would have to be asserted to "comparable"
>> which I guess is not possible as it is a contract). Or, the compiler could
>> be smart enough to know that if we reached that check, then the type must
>> be comparable (so it would also not give an error).
>>
>> In the current design draft, that would not work.  The == operator is
>> not supported by all possible types, so it is not permitted.
>>
>> We definitely don't want to rely on the compiler being smart enough.
>> Any such approach would require writing down the exact inference rules
>> that the compiler is permitted to use.  Otherwise different compilers
>> would behave differently.
>>
>> One possibility we've toyed with is
>>
>> switch T.(type) { // Note: switch on type parameter itself, not a
>> value of that type.
>> case Equaler:
>> ...
>> case comparable:
>> // Permit using == operator here on values of type T in this case
>> only.
>> }
>>
>> We'll see whether some such facility seems useful.  This is something
>> we can add later, if the current design draft seems workable.
>>
>> Ian
>>
> --
> 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/CAEd86Tz4tvx3qPZ4fV86AyV-B8YOXEMZMR-L4f6fcTyAuX_eXQ%40mail.gmail.com
> 
> .
>

-- 
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/CAEkBMfELVwJEkyLUJUsKGjUzqBVofDNRtkjta7%2BVXEFN_ZGtUg%40mail.gmail.com.


Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-02 Thread Bruno Albuquerque
Ok, it makes sense. I do think that supporting something like this might
make the proposal even more appealing as it will bring custom types
somewhat closer to builtin types by allowing generic functions/methods that
can act on both at the same time.

On Fri, Aug 2, 2019 at 1:28 PM Ian Lance Taylor  wrote:

> On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque  wrote:
> >
> > I was thinking about a way to  "extend" usual operations (say, equality
> checks) to types that can not be compared the usual way (they are not
> "comparable" in the contract sense) and came up with something like this:
> >
> > // Just to use for type assertion later.
> > type Equaler interface {
> >   Equal(Equaler) bool
> > }
> >
> > contract Comparable(T) {
> >   T comparable(T), Equal(T) bool
> > }
> >
> > func Compare(type T Comparable)(a, b T) bool {
> >   if eq, ok := a.(Equaler); ok {
> > return eq.Equal(b)
> >   }
> >
> >   return a == b  // Does this work at all?
> > }
> >
> > Would this work? More specifically it looks to me that that if the
> specific type is not comparable (But has the Equal method), the compiler
> might see the "==" comparison in the function and give an error.
> >
> > One way around this would possibly be to use something similar to type
> assertion (in this case, a and b would have to be asserted to "comparable"
> which I guess is not possible as it is a contract). Or, the compiler could
> be smart enough to know that if we reached that check, then the type must
> be comparable (so it would also not give an error).
>
> In the current design draft, that would not work.  The == operator is
> not supported by all possible types, so it is not permitted.
>
> We definitely don't want to rely on the compiler being smart enough.
> Any such approach would require writing down the exact inference rules
> that the compiler is permitted to use.  Otherwise different compilers
> would behave differently.
>
> One possibility we've toyed with is
>
> switch T.(type) { // Note: switch on type parameter itself, not a
> value of that type.
> case Equaler:
> ...
> case comparable:
> // Permit using == operator here on values of type T in this case
> only.
> }
>
> We'll see whether some such facility seems useful.  This is something
> we can add later, if the current design draft seems workable.
>
> Ian
>

-- 
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/CAEd86Tz4tvx3qPZ4fV86AyV-B8YOXEMZMR-L4f6fcTyAuX_eXQ%40mail.gmail.com.


Re: [go-nuts] Generics Draft: Mixing types and methods.

2019-08-02 Thread Ian Lance Taylor
On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque  wrote:
>
> I was thinking about a way to  "extend" usual operations (say, equality 
> checks) to types that can not be compared the usual way (they are not 
> "comparable" in the contract sense) and came up with something like this:
>
> // Just to use for type assertion later.
> type Equaler interface {
>   Equal(Equaler) bool
> }
>
> contract Comparable(T) {
>   T comparable(T), Equal(T) bool
> }
>
> func Compare(type T Comparable)(a, b T) bool {
>   if eq, ok := a.(Equaler); ok {
> return eq.Equal(b)
>   }
>
>   return a == b  // Does this work at all?
> }
>
> Would this work? More specifically it looks to me that that if the specific 
> type is not comparable (But has the Equal method), the compiler might see the 
> "==" comparison in the function and give an error.
>
> One way around this would possibly be to use something similar to type 
> assertion (in this case, a and b would have to be asserted to "comparable" 
> which I guess is not possible as it is a contract). Or, the compiler could be 
> smart enough to know that if we reached that check, then the type must be 
> comparable (so it would also not give an error).

In the current design draft, that would not work.  The == operator is
not supported by all possible types, so it is not permitted.

We definitely don't want to rely on the compiler being smart enough.
Any such approach would require writing down the exact inference rules
that the compiler is permitted to use.  Otherwise different compilers
would behave differently.

One possibility we've toyed with is

switch T.(type) { // Note: switch on type parameter itself, not a
value of that type.
case Equaler:
...
case comparable:
// Permit using == operator here on values of type T in this case only.
}

We'll see whether some such facility seems useful.  This is something
we can add later, if the current design draft seems workable.

Ian

-- 
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/CAOyqgcW%2BR%3D6FPQFLTexuP_FBTT6ibGo0aoDo_Xcjgf7i0zC9UQ%40mail.gmail.com.


[go-nuts] Generics Draft: Mixing types and methods.

2019-08-02 Thread Bruno Albuquerque
I was thinking about a way to  "extend" usual operations (say, equality
checks) to types that can not be compared the usual way (they are not
"comparable" in the contract sense) and came up with something like this:

// Just to use for type assertion later.
type Equaler interface {
  Equal(Equaler) bool
}

contract Comparable(T) {
  T comparable(T), Equal(T) bool
}

func Compare(type T Comparable)(a, b T) bool {
  if eq, ok := a.(Equaler); ok {
return eq.Equal(b)
  }

  return a == b  // Does this work at all?
}

Would this work? More specifically it looks to me that that if the specific
type is not comparable (But has the Equal method), the compiler might see
the "==" comparison in the function and give an error.

One way around this would possibly be to use something similar to type
assertion (in this case, a and b would have to be asserted to "comparable"
which I guess is not possible as it is a contract). Or, the compiler could
be smart enough to know that if we reached that check, then the type must
be comparable (so it would also not give an error).

-- 
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/CAEd86TxWSc4VajyWj0J2quMP4uJC095Z1uZced4aiuV4e8St7g%40mail.gmail.com.