-
Notifications
You must be signed in to change notification settings - Fork 18.9k
Description
go version devel +abe4d3dce1 Tue Dec 8 17:59:47 2020 +0000 linux/amd64
Proposal to allow type-parameterized method definition in go2go
Introduction
The relevant section of the current proposal can be found here.
The idea
It's simple: Disallow type-parameterized methods in interface bodies only.
To illustrate what I mean (excerpt from the proposal):
type HasIdentity interface {
Identity[T any](T) T // <- Make this line illegal.
}
But do allow the line (also from the proposal):
func (S) Identity[T any](v T) T { return v } // <- Make this line legal.
The arguments
Symmetry
Go methods are syntactic sugar for functions. They're one and the same, receivers are first arguments. An example:
package main
import (
"fmt"
)
type T string
func (t T) SayHello() { fmt.Printf("Hello, %s!", t) }
func main() {
// Method notation.
T("Gopher").SayHello()
// Function notation.
(T.SayHello)("Gopher")
}
Making a distinction between functions and methods would break this symmetry.
Usefulness
An obvious use-case that comes to mind a Result type (a Functor in Haskell-speak):
type Result[T any] struct {
val T
err error
}
func(r Result[T]) Map[U any] (f func(T) (U, error)) Result[U] {
if r.err != nil {
return Result[U]{err: r.err}
}
val, err := f(r.val)
if err != nil {
return Result[U]{err: err}
}
return Result[U]{val: val}
}
func(r Result[T]) Value() (T, error) {
return r.val, r.err
}
Note how Map requires an additional type-parameter, U. Here's a (silly) way it could be used:
counter, err := httpGet("https://exam.ple/api"). // returns Result[*http.Response]
Map[*http.Response, []byte](func(res *http.Response) ([]byte, error) {
defer res.Body.Close()
return ioutil.ReadAll(res.Body)
}).
Map[[]byte, APIResponse](func(body []byte) (APIResponse, error) {
res := APIResponse{}
return res, json.Unmarshal(body, &res)
}).
Map[APIResponse, int](func(res APIResponse) (int, error) {
return res.Website.Daily.Visits, nil
}).
Value()
Other concepts that can be implemented in similar ways are e.g. Promises, Monads, Optionals, all kinds of pipelines (like map-reducers), transducers.