Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Go: own List type incompatible with own Functor type

In order to learn more about Go, generics, and functional programming, I implemented a List type (excerpt of list.go):

package funcprog

type Function[T any] func(T) T

type List[T any] []T

func (l List[T]) Map(f Function[T]) List[T] {
    var ys List[T]
    for _, x := range l {
        y := f(x)
        ys = append(ys, y)
    }
    return ys
}

Which works quite well (main.go):

package main

import (
    "fmt"

    "funcprog"
)

func main() {
    numbers := funcprog.List[int]{0, 1, 2, 3}
    twice := func(x int) int { return x * 2 }
    fmt.Println(numbers.Map(twice))
}
$ go run main.go
[0 2 4 6]

My List is actually a Functor, so I wrote this interface (functor.go):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

package funcprog

type Functor[T any] interface {
    Map(Function[T]) Functor[T]
}

However, If I want to use my List as a Functor (main.go, modified):

import (
    "fmt"

    "funcprog"
)

func demo[T int](f funcprog.Functor[T]) {
    fmt.Println(f.Map(func(x T) T { return x * 2 }))
}

func main() {
    numbers := funcprog.List[int]{0, 1, 2, 3}
    demo[int](numbers)
}

I get this error:

funcprog.List[int] does not implement funcprog.Functor[int] (wrong type for Map method)
    have Map(f funcprog.Function[int]) funcprog.List[int]
    want Map(funcprog.Function[int]) funcprog.Functor[int]

Isn’t my List[int] also a Functor[int], because List[T] satisfies Functor[T]?

>Solution :

When looking if a type implements an interface, go does not try to do "interface mapping" on the elements of the signature of that function, it only compares the exact signatures.

If you want to have your List[T] type implement your Functor[T] interface, you should change the signature of the Map() method :

func (l List[T]) Map(f Function[T]) Functor[T] {
    ...
}

To mention one extra point : this is not linked to generics, but to how type checking is implemented on interfaces.

Here is another example (without generics) :

type MyStr string

// MyStr implements fmt.Stringer
func (s MyStr) String() string {
    return string(s)
}

// but this method does not fulfill the Concatter interface below
func (s MyStr) Concat(x string) MyStr {
    return s + " " + MyStr(x)
}

type Concatter interface {
    Concat(s string) fmt.Stringer
}

var _ Concatter = MyStr("") // compilation error

https://go.dev/play/p/tKDGEXlYHyl

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading