斯威夫特:静态地"追加"元组类型

时间:2015-02-04 06:09:20

标签: templates swift tuples type-systems flatten

我在写的Swift库中有一个模板化的结构。这个结构有两个特征:

  • 每个结构&#34;包装&#34;或&#34;代表&#34;另一种任意类型。 Foo<T>包裹T
  • 这些结构可以&#34;组合&#34;形成第三个结构,其代表的类型应该是&#34;组合&#34; (读:元组)前两个。在另一个世界中,如果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目前的模板功能和类型系统可能无法实现。尽管如此,如果任何人都可以提供一种解决方法,一开始就没有遇到这个问题的重新设计,或者在概念上类似但与我尝试做的事情不相同的事情,这将是非常有帮助的。事实上,我陷入了僵局。

1 个答案:

答案 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)>