我在写的Swift库中有一个模板化的结构。这个结构有两个特征:
Foo<T>
包裹T
fooA: Foo<A>
和fooB: Foo<B>
,则fooA + fooB
应为Foo<(A, B)>
类型。当只有两种类型要组合时,这很有效,但当你链接这个组合操作时,你开始得到嵌套的元组,这不是我想要的。例如,在以下代码中:
let a = Foo<A>(/* initialize */)
let b = Foo<B>(/* initialize */)
let c = Foo<C>(/* initialize */)
let d = a + b // type is Foo<(A, B)>
let e = d + c // type is Foo<((A, B), C)>
d
的类型为Foo<(A, B)>
,这是我们想要的,但e
的类型为Foo<((A, B), C)>
,这是一个额外的不需要的嵌套级别。
我需要某种方式来表达Foo<A>
和Foo<B>
的组合不是Foo<(A, B)>
,而是Foo<A + B>
,其中+
是假设的静态操作,这意味着&#34;如果第一种类型是元组类型,则将第二种类型附加到其上,从而产生一种新的非嵌套元组类型。如果它不是元组类型,只需创建元组类型(A, B)
。
这就像推动编译器(超出?)其极限一样,我怀疑使用Swift目前的模板功能和类型系统可能无法实现。尽管如此,如果任何人都可以提供一种解决方法,一开始就没有遇到这个问题的重新设计,或者在概念上类似但与我尝试做的事情不相同的事情,这将是非常有帮助的。事实上,我陷入了僵局。
答案 0 :(得分:1)
我认为没有通用的方法可以做到这一点。
也许,你可以这样做:
struct Foo<T> {
let v: T
init(_ v:T) { self.v = v }
}
func +<A,B>(lhs: Foo<(A)>, rhs:Foo<(B)>) -> Foo<(A,B)> { return Foo(lhs.v.0, rhs.v.0) }
func +<A,B,C>(lhs: Foo<(A,B)>, rhs: Foo<(C)>) -> Foo<(A,B,C)> { return Foo(lhs.v.0, lhs.v.1, rhs.v.0) }
func +<A,B,C>(lhs: Foo<(A)>, rhs: Foo<(B,C)>) -> Foo<(A,B,C)> { return Foo(lhs.v.0, rhs.v.0, rhs.v.1) }
func +<A,B,C,D>(lhs: Foo<(A,B,C)>, rhs: Foo<(D)>) -> Foo<(A,B,C,D)> { return Foo(lhs.v.0, lhs.v.1, lhs.v.2, rhs.v.0) }
func +<A,B,C,D>(lhs: Foo<(A,B)>, rhs: Foo<(C,D)>) -> Foo<(A,B,C,D)> { return Foo(lhs.v.0, lhs.v.1, rhs.v.0, rhs.v.1) }
func +<A,B,C,D>(lhs: Foo<(A)>, rhs: Foo<(B,C,D)>) -> Foo<(A,B,C,D)> { return Foo(lhs.v.0, rhs.v.0, rhs.v.1, rhs.v.2) }
// ... as many as you want ...
let f1 = Foo<(Int, UInt)>(1, 2) + Foo<String>("string") // -> as Foo<(Int, UInt, String)>