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 := (&a).(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 <b...@gmail.com> 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 <i...@golang.org> wrote: > >> On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque <b...@gmail.com> 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 > <https://groups.google.com/d/msgid/golang-nuts/CAEd86Tz4tvx3qPZ4fV86AyV-B8YOXEMZMR-L4f6fcTyAuX_eXQ%40mail.gmail.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/CAEkBMfELVwJEkyLUJUsKGjUzqBVofDNRtkjta7%2BVXEFN_ZGtUg%40mail.gmail.com.