特别是在 Swift 中(但老实说,我希望在任何类型语言中都有一个好的解决方案)我想正确键入一个 函数组合器函数。
我确实对类型语言和泛型有相当多的经验,但对 Swift 还很陌生。由于我一直在 Swift 中偶然发现这个问题,那就是 atm。我的主要关注点,但我认为我不确定如何在任何类型函数中执行此操作,而不简单地将所有内容声明为
Any
。
(教科书上的)问题是这样的:
(I) -> O
,其中 I
是数组中第一个函数的输入类型,O
是最后一个函数的输出类型。(PreviousOut) -> MyOut
类型,其中(当然)PreviousOut
是之前函数的输出类型。这是我到目前为止得到的:
func combine<I, O>(_ first: (I) -> Any, _ rest: ((Any) -> Any)...) -> (I) -> O {
return { input in
let firstResult = first(input)
return rest.reduce(firstResult) {$1($0)} as! O
}
}
...适用于
I
类型,但是当然 “无法推断通用参数 O
” 即使如此,我们在组合函数调用之间仍然没有任何类型的保存。
--更新-- 这是一个固定示例,其中包含 3 个确实有效的处理器功能。虽然这显然不是我想要实现的目标,但它可能更好地说明了需要什么:
func combine<I, O, A, B>(
_ first:@escaping (I) -> A,
_ second:@escaping (A) -> B,
_ third:@escaping (B) -> O
) -> (I) -> O {
return {input in third(second(first(input)))}
}
有什么想法吗?
不幸的是,即使考虑到新引入的类型参数包,你还是有点运气不好。
ATM,唯一的解决方案是编写
combine
函数的重载版本,这需要设置要支持的函数数量上限。
// zero functions
func combine() {
}
// one function
func combine<I, O>(_ f: @escaping (I) -> O) -> (I) -> O {
f
}
// two functions
func combine<I, O, T>(
_ f1: @escaping (I) -> T,
_ f2: @escaping (T) -> O
) -> (I) -> O {
{ f2(f1($0)) }
}
// three functions
func combine<I, O, T1, T2>(
_ f1: @escaping (I) -> T1,
_ f2: @escaping (T1) -> T2,
_ f3: @escaping (T2) -> O
) -> (I) -> O {
{ f3(f2(f1($0))) }
}
// four functions
func combine<I, O, T1, T2, T3>(
_ f1: @escaping (I) -> T1,
_ f2: @escaping (T1) -> T2,
_ f3: @escaping (T2) -> T3,
_ f4: @escaping (T3) -> O
) -> (I) -> O {
{ f4(f3(f2(f1($0)))) }
}
// and so on...
基本上,您必须在代码中手动编写所需数量的重载。