'Convert func(T) to func(any) [duplicate]

I want to be able to enforce similarity between two fields of a struct but also have several of these structs in a map or slice.

Here's a simplified example of my problem:

package main

type foo[T any] struct {
    f func() T
    v T
}

type bar struct {
    x []*foo[any]
}

func baz[T any](b *bar, f func() T) {
    b.x = append(b.x, &foo[any]{f: f})
}

func main() {
    var b bar
    baz(&b, func() int { return 0 })
}

The compiler complains

./prog.go:13:33: cannot use f (variable of type func() T) as type func() any in struct literal

The funny thing is that this can work if I didn't need to have a function pointer in the struct. See https://go.dev/play/p/qXTmaa9PuVe

So, is there a way for me to turn a T into an any?

I know I could do this with interface{}s and use reflect to enforce what I want, but I'm sure it's possible with only generics.

The context in case there is a way around my problem is that I'm making a flag package. The important structs look like this:

type flag[T any] struct {
    value T
    parse func(in string) (T, error)
    // Other fields removed for simplicity...
}

type FlagSet struct {
    // could flag[any] be replaced with a better answer?
    flags map[string]*flag[any]
    // Other fields removed for simplicity...
}

The question was closed so I have to put the answer to the second part of my question here

could flag[any] be replaced with a better answer?

The answer to the above is yes.

Solution:

Originally I though something like: "a func() fits a func() and an any fits a T so why can't I have a func() T fit a func() any?" Of course the reason is a func() any is not an any and so it cannot hold a func() T.

Instead, you can do the following:

package main

type foo[T any] struct {
    f func() T
    v T
}

func (f *foo[_]) set() {
    f.v = f.f()
}

type anyfoo interface {
    set()
}

type bar struct {
    x []anyfoo
}

func baz[T any](b *bar, f func() T) {
    b.x = append(b.x, &foo[T]{f: f})
}

func main() {
    var b bar
    baz(&b, func() int { return 0 })
}


Solution 1:[1]

but also have several of these structs in a map or slice

You cannot do this (in a type safe way). All values of e.g. a slice must have the same element type. If you want to store different ones you have to resort to interface{} and type switch later.

If you use the correct technical term parametric polymorphism instead of "generics" which doesn't explain what is going on you will see why func(T) and func(any) are different, unconvertable types.

So, is there a way for me to turn a T into an any?

No, there was no pre-"generics" way and there is no post-"generics" way. It helps to think of "turn into" as what Go allows: "type conversion" and "assignment". You can assign any variable of type T to a variable of type any.

You might overcome your issue by using an adaptor function (closure):

w := func(a any){ f(a.(T)) }
b.x = append(b.x, &foo[any]{w})

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 blackgreen