Home  >  Article  >  Backend Development  >  Why Does the `Pipe` Function Fail to Compile with Compatible Types in Go 1.18 Generics?

Why Does the `Pipe` Function Fail to Compile with Compatible Types in Go 1.18 Generics?

DDD
DDDOriginal
2024-11-17 10:30:04437browse

Why Does the `Pipe` Function Fail to Compile with Compatible Types in Go 1.18 Generics?

Contravariant Type Behavior in Go 1.18 Generics

Go 1.18 introduced generics, which allows for the creation of type-safe code. However, certain behaviors may differ from expectations, such as with contravariant types.

Consider the following function in Go 1.18:

func Pipe[A, T1, T2 any](left func(A) T1, right func(T1) T2) func(A) T2 {
    return func(a A) T2 {
        return right(left(a))
    }
}

This function is designed to pipe the output of left as the input to right. However, it fails to compile when used as follows:

func OpenFile(name string) *os.File {
    ...
}

func ReadAll(rdr io.Reader) []byte {
    ...
}

var OpenRead = Pipe(OpenFile, ReadAll)

This is because the compiler determines that T1 is *os.File, which is not identical to io.Reader even though it is compatible.

The desired behavior would be the ability to chain the Pipe function with functions that accept a compatible type as input. This aligns with the expected behavior when invoking the chain without generics.

Questions:

  1. Is there a way to adjust the signature of Pipe to allow for the desired behavior?
  2. Is this behavior by design or a bug?

Answers:

  1. No, there is currently no way to express compatibility between types using generics in Go 1.18.
  2. This behavior is not a bug. It reflects the lack of support for covariant result types in Go.

Workaround:

While it is not possible to achieve "compile-time type-safe" behavior, one possible workaround is to use type assertion:

func Pipe[A, T1, T2, T3 any](left func(A) T1, right func(T2) T3) func(A) T3 {
    return func(a A) T3 {
        return right(any(left(a)).(T2))
    }
}

This code is not type-safe at compile time, but it may provide the desired functionality in some cases.

The above is the detailed content of Why Does the `Pipe` Function Fail to Compile with Compatible Types in Go 1.18 Generics?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn