I write this kind of code a lot when working in Elm (whose generics are
in a similar spot to the place you suggest). It's not the worst, and
there various approaches in related languages use to make the "adaptors"
more ergonomic.

I still like the idea of using interfaces to express constraints better,
but I think it's worth discussing where this might go. Some
observations:

* We don't actually need an adaptor for the zero value, since we can
  just declare a variable of the generic type:

    func MyFn(type T) {
        // x is the zero value, per usual initialization rules:
        var x T

        // ...
    }
* If we don't have any kind of bounding on type variables, then we can
  actually omit type parameter lists entirely, and use a lexical
  convention to distinguish between concrete and generic types. OCaml
  does this by denoting type parameters with a single quote, so 't is a
  type variable while t is a concrete type. Borrowing that convention we
  could write e.g:

    func MapSlice(slice []'src, f func('src) 'dst) []'dst {
        // ...
    }

  ...which reduces verbosity a bit.

  Haskell and Elm both use case to distinguish, with uppercase variable
  names being concrete and lower case being type variables. I like that
  a bit better, but Go already uses case to distinguish exported vs.
  private.
* Your suggestion of default adaptors is similar to Scala's implicit
  parameters: https://docs.scala-lang.org/tour/implicit-parameters.html

One problem with this design, which bounding solves: Suppose we have a
generic set type implemented using binary trees (I will use
the 't notation discussed above, but you could use explicit parameter
lists as well).

    type Order('t) interface{
        Less(x, y 't)
    }

    type Set('t) struct {
        // ...
    }

    func (s Set('t)) Insert('t; Order('t))
    func (s Set('t)) Member('t; Order('t)) bool
    // etc.

What happens if we accidentally pass different adapters to different
calls to the methods? e.g:


    type CaseSensitive struct {}
    type CaseInensitive struct {}

    func (CaseSensitive) Less(l, r string) bool
    func (CaseInsensitive) Less(l, r string) bool

    // ...

    var set Set(string)

    set.Insert("Apple"; CaseInensitive{})
    set.Insert("Animal"; CaseInsensitive{})
    set.Insert("acorn"; CaseInsensitive{})

    // Returns false!
    set.Member("acorn"; CaseSensitive{})

Depending on scoping issues and how you infer the adaptors, this could
happen by accident, because of different adaptors being visible in
different scopes.

This is a known problem with scala implicits, whereas with rust
traits/haskell type classes, we're able to guarantee that there is only
one instance of an "adaptor" for a given type. But this means giving up
on automatic interface satisfaction, which is... no.

There's a paper that you'll find if you google "ocaml modular implicits"
that solves this issue for OCaml using OCaml's module system, and while
I have some ideas about how we *could* extend Go with the necessary
functionality, it's a much bigger change to the language than adding
bounds based on interfaces.

Quoting Patrick Smith (2018-10-16 06:33:39)
>    Yet another generics discussion
>    at� [1]https://gist.github.com/pat42smith/ccf021193971f6de6fdb229d68215
>    302
>    This one looks at what programmers would be able to do if very basic
>    generics were added to Go, without contracts. Generic functions may not
>    use methods or operators of their type parameters.
>    The answer is quite a lot, actually. The code would be verbose, but not
>    impossibly so.
>
>    --
>    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 [2]golang-nuts+unsubscr...@googlegroups.com.
>    For more options, visit [3]https://groups.google.com/d/optout.
>
> Verweise
>
>    1. https://gist.github.com/pat42smith/ccf021193971f6de6fdb229d68215302
>    2. mailto:golang-nuts+unsubscr...@googlegroups.com
>    3. https://groups.google.com/d/optout

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

Reply via email to