我正在为(有效地)排列库构建一个库;目标是允许您指定和组合n个元素上的排列.因此,例如,我希望能够执行以下操作:

let p1 = Permutation([4,3,2,1])
let p2 = Permutation([1,3,2,4])
p1 * p2 // -> Permutation([4,2,3,1])

一般来说,只有组成相同大小的排列才有意义.因此,例如:

let p3 = Permutation([1,2,3])
p1 * p3 // Error

显然,我可以在作文时判断大小,然后抛出异常或返回nil;但这两个选项都涉及更多的样板(要么用try标记每个作文,要么解包每个结果).因为组合不同长度的排列从来没有意义,所以我更希望有一个编译时错误--本质上,我希望不同长度的排列具有不同的类型.

我可以指定有限数量的类型--我的最终用例可能只关心有限的大小范围.但是,最终还会有其他类型的类型(例如,排列序列或排列的语义类型子集)将应用相同的限制-所以我更喜欢以某种通用的方式进行类型判断.

(如果有帮助,基本上我要寻找的是一种近似Julia的NTuple个类型的方法,这些类型由元素的数量来参数化.)

我try 过的东西

到目前为止,我最好的try 涉及虚拟长度的"类型"(即每个长度有一个单独的不可实例化的类型):

protocol LengthProtocol { }
enum Three: LengthProtocol { }
enum Four: LengthProtocol { }

struct Permutation<Length: LengthProtocol> {
  // ...

  static func *<S: LengthProtocol>(lhs: Permutation<S>, rhs: Permutation<S>) -> Permutation<S> {
    // ...
  }
}

然而,类型推断似乎失败了,如下所示:

let p1 = Permutation<Three>([1,2,3])
let p2 = Permutation<Three>([1,3,2])
p1 * p2 // ERROR: Cannot infer generic paramter S

推荐答案

运算符不应该是泛型的.它应该使用现有的Length类型参数,如 struct 中声明的那样.

static func *(lhs: Permutation<Length>, rhs: Permutation<Length>) -> Permutation<Length> {
    ...
}

仅当您将运算符outside声明为Permutation时,才需要泛型参数S.

此外,我不允许公共代码使用数组来初始化Permutation.相反,使用特定数量的参数公开初始值设定项,并在每个初始值设定项上约束Length.

private init(_ array: [Int]) {
    // ...
}

init(_ a: Int, _ b: Int, _ c: Int, _ d: Int) where Length == Four {
    self.init([a, b, c, d])
}

init(_ a: Int, _ b: Int, _ c: Int) where Length == Three {
    self.init([a, b, c])
}

Swift相关问答推荐

DynamicView Content的修改视图?

在解码字符串时需要帮助.

如何在枚举有关联数据时使用combined if with case

SwiftUI-如何使用剩余时间制作倒计时计时器

如何观察UIViewRepresentable中的多个变化?

在 SwiftUI 视图中观察 UIViewRepresentable 的 @State var 变化

Swift ui 转换无法按预期工作

CardStack 和 Lottie

如何使一个 Reality Composer 场景中的分组对象可拖动?

Swift Combine:如何在保留发布者结果顺序的同时进行收集?

如何在类中打印函数

如何在 SWIFTUI 中旋转修剪?

如何从另一个 swift 文件中调用函数

SwiftUI - Select 器没有 Select 值

如何快速制作虚线?

在 Swift 中获取双精度的小数部分

在 Xcode 中自动实现 Swift 协议方法

使用 phimagemanager 将图像保存到自定义相册?

Swift 2.0 按属性对对象数组进行排序

iOS 视图可见性消失了