What you appear to be after is a recursive relationship with union types: "S is a slice type, each of whose elements are either of type S or some type T".
Exactly this is what I'm trying to emphasize: since I'm opting to use the explicit generic type inference, I would expect the type system to "detect" the type I've defined as a generic type constraint even though the type parameter is not strictly related to the T type constraint. If I'd be using baseFlatten[T any](acc []T, slice T) ([]T, error) this won't be an issue, but in this case I'd be forced to use float32 instead of any, which I would like to avoid. So I'm out of ideas how this situation could be overcome without explicitly defining the parameter's type. Maybe posting a proposal? On Tuesday, August 9, 2022 at 2:16:05 PM UTC+3 Brian Candler wrote: > Example of type inference in action: > https://go.dev/play/p/pL7_8zaFIZN > > What you appear to be after is a recursive relationship with union types: > "S is a slice type, each of whose elements are either of type S or some > type T". AFAIK Go's type system isn't rich enough for that: hence for > heterogenous slices you're stuck with interface types (including "any", > which is a shortcut for the empty interface, "interface {}") > > On Tuesday, 9 August 2022 at 11:53:11 UTC+1 Brian Candler wrote: > >> As far as I can see, the problem isn't anything to do with generics, but >> with this line alone: >> input := []any{[]float32{1.0, 2.0}, 1.1} >> >> See: >> https://go.dev/play/p/gUqmUb-Vs_y >> >> You've made a slice with mixed elements. One happens to be a slice of >> float32's, and the other happens to be a float64. Go has no idea that >> you'd prefer the second to be a float32. >> >> Generic type inference only happens locally at a function call site; it >> doesn't propagate backwards to the rest of your program. Furthermore: >> >> 1. When explicitly invoking Flatten[float32](...) you've bypassed the >> type inference, by forcing type T to be float32 >> 2. Type inference isn't possible for this function, because your >> function's argument (slice any) does not relate to any of the generic type >> parameters (i.e. it doesn't make use of "T") >> >> On Tuesday, 9 August 2022 at 11:08:42 UTC+1 esi...@gmail.com wrote: >> >>> Let's consider the following situation: >>> >>> I have generic function which can accepts function arguments defined as >>> any. Now if want to know exactly the type of function arguments I have to >>> use the reflect package. The problem is that although on function >>> invocation we can explicitly define the type constraints, these are not >>> taken into consideration when we are matching the concrete types using the >>> reflect type switch. >>> >>> So let's say, that I have the following function: >>> >>> // Flatten flattens the slice all the way to the deepest nesting level. >>> func Flatten[T any](slice any) ([]T, error) { >>> return baseFlatten([]T{}, slice) >>> } >>> >>> func baseFlatten[T any](acc []T, slice any) ([]T, error) { >>> var err error >>> >>> switch v := any(slice).(type) { >>> case T: >>> acc = append(acc, v) >>> case []T: >>> acc = append(acc, v...) >>> case []any: >>> for _, sv := range v { >>> acc, err = baseFlatten(acc, sv) >>> if err != nil { >>> return nil, errors.New("flattening >>> error") >>> } >>> } >>> default: >>> return nil, errors.New("flattening error") >>> } >>> >>> return acc, nil >>> } >>> >>> I would expect that calling the Flatten method in the following way, the >>> types to be inferred correctly and the input values to be recognized as >>> float32 and NOT float64. Because otherwise I don't see the reason to use an >>> explicit type constraint on function invocation. >>> >>> input := []any{[]float32{1.0, 2.0}, 1.1} >>> result, err := Flatten[float32](input) >>> >>> The generic type switch cases as defined in the proposal ( >>> https://go.googlesource.com/proposal/+/HEAD/design/43651-type-parameters.md#generic-types-as-type-switch-cases) >>> >>> is not intuitive, at least for me. >>> >>> Now the question is how could I infer correctly the parameter type >>> without explicitly defining the value 1.1 as float32 like this: >>> >>> input := []any{[]float32{1.0, 2.0}, float32(1.1)} >>> result, err := Flatten[float32](input) >>> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/c052db47-96a3-4e2c-8db4-d29784988599n%40googlegroups.com.