В golang 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))
}
}
например вывод функции left
должен быть вводом функции right
, представленным в виде дженериков.
Я замечаю, что это не работает должным образом для следующего примера:
func OpenFile(name string) *os.File {
...
}
func ReadAll(rdr io.Reader) []byte {
...
}
var OpenRead = Pipe(OpenFile, ReadAll)
Это не удается скомпилировать, потому что компилятор считает T1
*os.File
, и хотя он совместим с io.Reader
, он не идентичен.
Если бы я вызывал цепочку без таких шаблонов:
var result = ReadAll(OpenFile("test"))
затем компилятор идентифицирует совместимые типы.
Вопросы:
Pipe
, чтобы обеспечить желаемое поведение?Учитывая, что Go не поддерживает ковариантные типы результатов, вам нужно преобразовать результат left
в тип, принятый right
. Однако в настоящее время нет способа выразить конвертируемость использует параметры типа.
Если вы хотите, вы можете адаптировать свой код на основе примера в этой ссылке, и вы получите что-то вроде это, но имейте в виду, что это не "безопасно для типов во время компиляции".
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((interface{})(left(a)).(T2))
}
}
Спасибо за разъяснение. Надеюсь, со временем это изменится...