Am 21. März 2021 22:01:38 MEZ schrieb Ian Lance Taylor <i...@golang.org>:
>On Sun, Mar 21, 2021 at 1:02 PM Martin Leiser <leiser.1...@gmail.com>
>wrote:
>>
>> I think so. But How? Remember we need to do two things:
>>
>>     - A way to define type parameters.
>>
>>     - A way to bind the type parameters to concrete types at compile
>time
>
>Thanks for the note.
>
>I think that a generics proposal needs to do three things.  The third
>is that it needs to describe which operations are permitted for a type
>parameter.
Absolutely correct.
Especially if you think about the kind of things you may do with type 
parameters and type inference in languages like Haskell or ML.
The only thing you aktually want to do with binding types of type parameters 
is: use them as parameters of your package.
No difference to the accepted proposal here.
The key difference here is the way to define and bind the parameters.
All else should be as equal as possible, because the accepted proposal is good.
>
>
>> But after we named it "ElementType" we can get a hold of it and bind
>it in the package we intend to use e.G. a "list of strings":
>>
>>     import "container/list"  type ElementType string
>
>This general kind of idea has been suggested quite a few times before.
>Here are a few examples:
>
>https://gist.github.com/PeterRK/41d4d3f54b8db55cd616403fd5a389f3
>https://github.com/dotaheor/unify-Go-builtin-and-custom-generics/blob/master/use-package-as-gen.md
>https://groups.google.com/g/golang-nuts/c/xKYXZpsWHus/m/SS4FKMBEAQAJ
>
>There are others.
>
yes I know about eg. even older ones like genny 
https://github.com/cheekybits/genny
>
>> Last features. If you need two different bindings in one package, say
>a list of string and a list of int you may use:
>>
>>     import "container/list" intlist  type ElementType = int
>>
>>     import "container/list" stringlist type ElementType = string
>
>What if I want to have a list of lists of strings?
That is a no brainer. The type "list of strings" in the example is: 
"stringlist.Element". So you add the following line:
   import "container/list" liststringlist type ElementType = stringlist.Element
>
>What if I want to have a list of some unexported type that I defined
>in this package?
That is the "Complicated" part of the proposal. It can be solved and it is not 
that tricky:
- All the compiler really needs to know about the bound type is specified by 
the bound interface type, plus the storage size.
- You have to outrule cyclic definitions, but they are impossible, because it 
is the implementaion which introduces the cycle.
- You may even fall back to the normal implementation of "interface types" 
behind the scenes when appropriate.

Semantically all is solved by the following three program transformations 
chained together:
1. Make the private Type exported (does not change behaviour as long as you 
avoid name clashes by consistent renaming)
2. Add an import to the Package defining the binding type in a renamed copy of 
the generic package
3. replace the definition of the bind type by a type alias with the binding 
type in the copy of step 2
In my posting I only named the 3. transformation to keep things simple.
Steps 2 and 3 have to be done at most once for any binding type in the whole 
program.
All this may be implemented as "source to source" transformations,
as you may know from the compiler construction class talking about generics
(mine was >30 years age full of examples from LIS and Ada, I am a bit rusty 
here).
And it gets way more complicated when you actually start to do it in reality.
But it is this simple to describe here, because I choose to bind on the package 
level.
That is part of the trick. The price are global variables.

But can You always apply this transformation? Are there additional limitations 
required? I do not know yet.
I believe you must outrule a import cycle for the type binding import. Which 
should be of no practical impact.

>  That seems to require interweaving type definitions
>and imports in ways that the language does not currently support.
Hmm, do not think so, see above. The result of the program transformation above 
should be a valid Go 1 program.

For every type binding you have to have a way to "instantiate" a copy of the 
whole package with this binding.
And the "stringlist" must only have one instantiation for all packages using 
the same type binding imports.
Doing this efficient and effective, that is the complicated part.

Did I mention that there is no big difference in complexity in the 
implementation of my proposal and the accepted one?
Sorry for ommiting that.
I actually see an additional risk, when talking about global variables 
involving the parameter types.
(Which makes no sense for practical use, but has to be covered or outruled.)

>
>With this proposal, how can I write a min function that works for any
>integer type, including a user-defined integer type?  
No. I did not include user-defined types. Buf if You add the enumerated 
interface types of the accepted proposal to the language,
this works just fine for my proposal as well. I talked about "named interface 
types". Whatever is a legal interface type works just fine.
So it this part of the the proposal is added to the language it works just fine 
for me.

> What happens if
>I try to import a package that defines that Min function but I set the
>argument type to some that does not support the < operator?
I would simply write two similar packages: one using the above mentioned 
enumerated interface of the accepted draft,
and another using the
        type Lesser interface {Less(Lesser) Lesser }
The implementation of min with Lesser:
   func Min(a, b Lesser) Lesser { if a.Less(b) {return a;} else {return b;}}
The implementation of Min with "ComparableStdType" stolen from the accepted 
draft:
   func Min(a, b ComparableStdType) ComparableStdType {if a < b {return a; } 
else {return b;}

The idea of the "interface with enumerated standard types" a really good 
example for simplicity in the accepted draft.
Not adding operator overloading to Go is a good thing.

The builtin stuff is tricky to deal with, but IMHO this could also be solved 
"the other way around":
Define a set of "Builtin Standard Type Definition Packages" containing all the 
methods
(it has to be methods, because of interface types which may be used as 
functions effortlessly):
      Plus Minus Multiply Define Less Equal
etc. and define the operators to be more or less a short hands of this Methods.
This would solve the "builtin special case" as well, and eliminates the need to 
treat the builtin types as special cases, e.g. in the "sort.go" package.
The implementation of this builtin packages should of course still be "well 
known to the compiler" in oder to spill out efficient code.
But is this really simpler than enumerating the special types? I think so, but 
no strong arguments here.

Doing it this way eliminates the need for two definitions of the "Min" function 
for sure, because int simply has a method "Less" now as a synonym for the 
operator <.
And it would be a perfect starting point for describing the methods I should 
add to my type,
when trying to implement a "Comparable" type in my own code.

Looking at the Haskell or ML standard libraries is a good starting point for 
evaluating "generic" additions to the standard library IMHO.
There is e.g. the numerical type class there, I found it helpful for 
understanding Haskell to treat the Haskell "type class" the same as "interface 
type" in Go.

Except for the "sort.go" Package there isn't much functional stuff in the Go 
standard library to choose from when making a proposal.
(And I learned You should use examples from the standard library when making 
proposals, so I focused on containers.)

Hopefully this will change soon after "generics" are added!

>
>Thanks again.
>
>Ian

Thanks for your quick response.

Martin

-- 
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/B21BFCCF-B3BF-4522-86AE-F606595C532A%40gmail.com.

Reply via email to