我正在尝试弄清楚如何设置中间件,目前我的代码是这样的:
func applyMiddleware(h *Handle) *Handle {
return a(b(c(h)))
}
有没有一种方法可以“组合”这些函数,这样我只需要传递一个Handle(s)列表,它就会返回组合的函数?
我正在尝试弄清楚如何设置中间件,目前我的代码是这样的:
func applyMiddleware(h *Handle) *Handle {
return a(b(c(h)))
}
使用切片
https://play.golang.org/p/DrEnGkIEbU3
package main
import (
"fmt"
)
func main() {
fmt.Println(v(v(v(0))))
fmt.Println(compose(v, v, v)(0))
}
func v(i int) int {
return i + 1
}
func compose(manyv ...func(int) int) func(int) int {
return func(i int) int {
for _, v := range manyv {
i = v(i)
}
return i
}
}
func compose[A any, B any, C any](f func(A) B, g func(B) C) func(A) C {
return func(a A) C {
return g(f(a))
}
}
compose
的组合顺序是从左到右,即 compose(f, g)
返回函数 "f 后的 g" 或 g ∘ f,在 Haskell 中等同于 g . f
,在 F# 或 Elm 中等同于 f >> g
。
换句话说,结果函数 compose(f, g)
的输入被馈送到 f
,然后将 f
的输出馈送到 g
,其输出是最终结果:
首先,让我们定义类型Adapter
来表示您想要组合的函数类型:
type Adapter = func(*Handle) *Handle
使用 compose
和 Adapter
,您现在可以定义 composeAdapters
来组合任意数量的这些 Adapter
函数:
func composeAdapters(adapters ...Adapter) Adapter {
composition := func(h *Handle) *Handle {
return h
}
for _, adapter := range adapters {
composition = compose(composition, adapter)
}
return composition
}
*Handle
,composition
被初始化为identity function。您可以将其视为no-op adapter:如果有任何要组合的第一个函数,则它只会将输入转发到结果组合适配器中。这也意味着调用没有任何参数的composeAdapters
- 例如,composeAdapters()
- 将导致无操作适配器:它不对输入*Handle
执行任何操作;它只是将其返回。Adapter
(即func(*Handle) *Handle
)的函数f
、g
和h
,applyMiddleware
可以实现为:var applyMiddleware = composeAdapters(f, g, h)
// functor via embedding
type Functor[A any, B any, C any] interface {
fmap(func(A) B) C
}
// holding the "function" type in a way that is compatible with Functor
type Wtf[R any, A any, B any] func(R) A
// implementation/instance of Functor for anonymous functions!
func (g Wtf[R, A, B]) fmap(f func(A) B) Wtf[R, B, A] {
h := func(t R) B { return f(g(t)) }
var funout Wtf[R, B, A] = h
return funout
}
Wtf[R,B,A]
,而不是fn(R)B
,以允许组合操作的链接。func main(){
var f1 Wtf[int, int, int] = func(t int) int { return 1 * t }
f2 := func(t int) int { return 2 * t }
f3 := func(t int) int { return 3 * t }
fmt.Println((f1.fmap(f2).fmap(f3))(7)) // 42
}
f1 |> f2 |> f3
)。map
函数中看到的行为(不要与Go语言中同名的函数混淆)。
func(*Handle) *Handle
,否则它不是有效的 Go 代码。 - user4466350