Skip to content
This repository has been archived by the owner on Sep 20, 2022. It is now read-only.

Type Parameter Constraints #11

Open
jeromefroe opened this issue Jun 14, 2018 · 4 comments
Open

Type Parameter Constraints #11

jeromefroe opened this issue Jun 14, 2018 · 4 comments
Assignees
Labels
enhancement New feature or request

Comments

@jeromefroe
Copy link

Hi! I was wondering what your thoughts were on supporting type constraints so that one could require that a type T must implement a certain interface. For example (playground):

package main

import "fmt"

type Describer interface {
 	Describe() string
}

type A struct {}

func (a A) Describe() string { return "A" }

func Description[T](t T) string {
	return t.Describe()
}

func main() {
      	a := A{}
	fmt.Println(Description[A](a))
}

This program fails to compile with the following error:

main.go:14:9: invalid operation: t (variable of type T) has no field or method Describe

which makes sense since we don't require that the type T in Description implements Describer so we can't call Describe on t. But we could perhaps constrain T to require that it implements Describer:

func Description[T: Describer](t T) string {
	return t.Describe()
}

Then we could safely call Describe because the compiler will enforce that all types T implement Describer. Supporting such a feature might make it possible to use generics in more places where interfaces are used currently. Anyway, just interested in what your thoughts were. Thanks!

P.S. This project is really cool!

@albrow
Copy link
Owner

albrow commented Jun 15, 2018

Thanks for creating this issue. It's already something I'm planning to add and I don't expect it to be too difficult. Internally, the type-checker considers type parameters to have underlying type interface{}. A constraint on a type parameter should be as straightforward as changing it's underlying type to a specific named interface instead of an empty one. The only tricky bit I can see is thinking about how this would work with generic interfaces or whether we should allow other kinds of type constraints (e.g., sum types).

@albrow albrow self-assigned this Jun 15, 2018
@albrow albrow added the enhancement New feature or request label Jun 15, 2018
@jeromefroe
Copy link
Author

Very cool, sounds like it should fit in nicely with the current implementation then. I'm not sure what you mean by how it would work other kinds of type constraints though. A generic sum type makes me think of something like the following:

type Plottable = T: Cartesian | U: Polar

@albrow
Copy link
Owner

albrow commented Jun 15, 2018

Here's what I was referring to regarding type constraints and sum types. Suppose you have a generic add function:

func add[T](x, y T) T {
    return x + y
}

What you really would like to do here is constrain T to be one of the builtin numeric types: int, uint, float64, etc. Since interfaces in Go (and in Fo, currently) only encapsulate methods, you can't use an interface to describe this constraint. We could modify the concept of interfaces to allow this, but I would like to minimize the number of changes Fo makes to the language, and I like the design of Go's interfaces as they are today.

What I'm considering is that you could have a (possibly built-in) sum type numeric that looks like this:

type numeric = int | uint | float64 // etc.

Then you can add a type constraint to the add function like this:

func add[T numeric](x, y T) T {
    return x + y
}

(This brings up a question about how the + operator should relate to type constraints, but let's set that aside for the moment).

Maybe this is not worth the complexity and we should just stick to interfaces as the only kind of type constraint. I just thought it was worth mentioning as something I'm considering.

@jeromefroe
Copy link
Author

Ahh, thanks for the clarification, I like the idea! Perhaps another approach would be to support generic interfaces, in which case you could define a generic Numeric interface and implement it for the built-in types. I'm thinking something like the following:

type Numeric[T] interface {
    func Add(other T) T
    func Subtract(other T) T
    ...
}

func (i int) Add(o int) int {
    return i + o
}

...

@albrow albrow changed the title Supporting Type Constraints? Type Parameter Constraints Aug 11, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants