Sorry, I was thinking that Foo was an interface (rather than an existing contract), so the second example couldn't be written non-generically.
In the third example you could also merge the two contracts into one: contract MapFoo(K, V) { Comparable(K) union{ int, float64, complex128 }(V) interfaceA(V) } func mapper(type K, V MapFoo)(m map[K]V, ...) ... { // do something with m } Alan On Tuesday, September 18, 2018 at 7:42:06 PM UTC+1, alan...@gmail.com wrote: > > Just going through how xingtao zhao's examples would look under my own > proposal: > > The first one would be: > > contract Foo(T) { > union{ int, float64, complex128 }(T) > interfaceA(T) > } > > Note though that this could only be satisfied by defined types based on > int, float64 or complex128 as those types don't have methods themselves and > so couldn't satisfy interfaceA. > > > The second one would be approached in a different way which doesn't > require the slice element type to be deduced or a contract to be written: > > func slicer(type T Foo)(s []T, ...) ... { > // do something with s > } > > or even non-generically: > > func slicer2(s []Foo, ...) ... { ... } > > > The third one would also be approached in a different way but still > requires a contract: > > contract Map(K, V) { > Comparable(K) > Foo(V) > } > > func mapper(type K, V Map)(m map[K]V, ...) ... { > // do something with m > } > > Finally, a struct type with a field f (say of type int) could be expressed > like this: > > contract Struct(T) { > struct{ f int }(T) > } > > Alan > > On Tuesday, September 18, 2018 at 5:51:03 PM UTC+1, xingtao zhao wrote: >> >> I have the similar thought as the thread. In terms of a contract, it is >> mainly to express these: >> >> 1. Methods set: this could be easily expressed by interface >> 2. Operators set: In go, we could not add or remove the existing >> operator set for a given type, which is completely inherited from its >> underlying type. So it is equivalent to explicitly express operation set >> vs >> to express the union of underlying types. >> 3. Type conversion: >> 1. conversion between types with the same underlying type >> 2. conversion between numeric types >> 3. conversion from concrete types to interface >> >> So it is obviously that what we are lacking is: expressing underlying >> types and expressing the combination of them, i.e. union type. So maybe a >> contract could be written like this: >> >> contract Foo(T) { >> int(T) || float64(T) || complex128(T) // underlying type: int, >> float64, complex128 >> InterfaceA(T) // at the same time, >> it should satisfy InterfaceA >> } >> >> contract Slice(S) { >> []T(S) && Foo(T) // S is a slice, and retrieve the element type to >> T, and T should match contract Foo >> } >> >> contract Map(M) { >> (map[K]V)(M) && Foo(V) // M is a map, whose value type match contract >> Foo. >> } >> >> There is still no way to express that a type should have a field "f" - >> But maybe we can accept this? >> >> In this case, contract is more orthogonal to the existing concepts in go >> - we already have the way to express the method set of a type (interface), >> it is no needed to be able to express it in contract again. >> >> >> On Monday, September 17, 2018 at 4:54:04 PM UTC-7, alanfo wrote: >> >>> Thanks for your comment, Patrick. >>> >>> Although I've relied on compiler magic for my previous proposals, I >>> believe we should keep it to a minimum if we can, The 'union' and 'except' >>> idea would allow us to compose any group of types we want from the basic >>> built-ins and, even within the standard library, it would always be clear >>> from looking at the underlying code exactly what those groups comprised. >>> >>> For me that would be a valuable feature and would still be significantly >>> less complex than the draft generics design where every operator used has >>> to be spelled out. Under this proposal, the allowable operators/conversions >>> etc. are implicit from the types used. >>> >>> Alan >>> >>> On Monday, September 17, 2018 at 8:16:38 PM UTC+1, Patrick Smith wrote: >>>> >>>> I think your idea of creating standard contracts to represent similar >>>> types is a good one. However, you don't have to say how those contracts >>>> are >>>> written, just what they do. No need for typecheck, union, except, etc. For >>>> example, >>>> >>>> Integer(T) - T is an integer type >>>> Float(T) - T is a floating point type >>>> Complex(T) - T is a complex type >>>> >>>> For contracts in the standard library, we can just invoke "compiler >>>> magic" to explain how they work. Trying to explain the mechanism merely >>>> adds complexity. >>>> >>> -- 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. For more options, visit https://groups.google.com/d/optout.