Skip to content

proposal: Go 2: allow type-parameterized methods. #43390

@thwd

Description

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions