将 Range 和 StrideTo 转换为 Sequence 时出现特殊错误

Peculiar errors while converting Range and StrideTo into Sequence

以下函数产生编译器错误

func iterateColumnsAlongGravity<S: Sequence>(using block: (_ indexes: S) -> ())
    where S.Element == Int {

        switch gravityDirection {
        case .bot:
            for i in stride(from: 0, to: w * h, by: h) {
                // 'Range<Int>' is not convertible to 'S'
                block(i..<(i + h))
            }
        case .top:
            for i in stride(from: 0, to: w * h, by: h) {
                // 'ReversedCollection<(Range<Int>)>' is not convertible to 'S'
                block((i..<(i + h)).reversed())
            }
        case .left:
            for y in 0..<h {
                let indexes = stride(from: y, to: w * h, by: h).reversed()
                // '([Int]) -> ()' is not convertible to '(S) -> ()'
                block(indexes)
            }
        case .right:
            for y in 0..<h {
                // '(StrideTo<Int>) -> ()' is not convertible to '(S) -> ()'
                let indexes = stride(from: y, to: w * h, by: h)
                block(indexes)
            }
        }
}

我不明白为什么 编译器不将 Range<Int> 转换为 S(以及其他类型),而 Range显然符合Sequence,它的元素是Int

奇特,如果我将block替换为具有类似签名的class方法,没有任何错误

func printIntSequence<S: Sequence>(_ s: S) where S.Element == Int {
    for i in s {
        print(i)
    }
}

func typeConversionTest() {
    switch gravityDirection {
    case .bot:
        for i in stride(from: 0, to: w * h, by: h) {
            printIntSequence(i..<(i + h))
        }
    case .top:
        for i in stride(from: 0, to: w * h, by: h) {
            printIntSequence((i..<(i + h)).reversed())
        }
    case .left:
        for y in 0..<h {
            let indexes = stride(from: y, to: w * h, by: h).reversed()
            printIntSequence(indexes)
        }
    case .right:
        for y in 0..<h {
            let indexes = stride(from: y, to: w * h, by: h)
            printIntSequence(indexes)
        }
    }
}

iterateColumnsAlongGravity(using:)typeConversionTest()的唯一区别是第一个以块为参数。

the discussion 期间 Swift 论坛上透露了以下信息:

  1. 我试图实现的是所谓的高阶多态性,这个重要的特性还没有添加到 Swift。
  2. 可能最简单的解决方案是丢弃泛型并在此处使用 StrideTo<Int>

    func iterateColumnsAlongGravity(using block: (_ indexes: StrideTo<Int>) -> ()) {
        switch gravityDirection {
        case .bot:
            for i in stride(from: 0, to: w * h, by: h) {
                block(stride(from: i, to: i + h, by: 1))
            }
        case .top:
            for i in stride(from: 0, to: w * h, by: h) {
            block(stride(from: i + h - h, to: i - h, by: -1))
            }
        case .left:
            for y in 0..<h {
                block(stride(from: (w - 1) * h + y, to: -1, by: -h))
            }
        case .right:
            for y in 0..<h {
                block(stride(from: y, to: w * h, by: h))
            }
        }
    }