通用类型在不透明类型的帮助下符合 Sequence:一些 IteratorProtocol

Generic type conforms to Sequence with help of opaque type: some IteratorProtocol

protocol TreeNode: AnyObject {
    associatedtype T
    var value: T { get set }
    var children: [Self] { get }
    init(_ value: T)
}

protocol Tree: Sequence {
    associatedtype Node: TreeNode
    var root: Node? { get set }
}

extension Tree {
    typealias T = Node.T
    
    func makeIterator() -> some IteratorProtocol {
        BFSIterator(startFrom: root)
    }
}

这个编译看起来很有前途。
但是突然在单元测试行 let sum = tree.reduce(0, +) 导致编译错误:

Cannot convert value of type '(Int) -> Int' to expected argument type '(Int, (some IteratorProtocol).Element) throws -> Int'

为什么编译器无法判断 (some IteratorProtocol).Element 确实是 Int?以及如何帮助它?

请注意,如果我采用“旧方法”(没有不透明类型): func makeIterator() -> BFSIterator { 一切都可以编译并完美运行。

更新:

struct BFSIterator<Node: TreeNode>: IteratorProtocol {
    private var queue: Queue<Node> = []
    
    init(startFrom root: Node?) {
        root.map { queue.push([=11=]) }
    }
    
    mutating func next() -> Node.T? {
        guard let current = queue.pop() else { return nil }
        queue.push(contentsOf: current.children)
        return current.value
    }
}

发生这种情况是因为当前 Swift (5.2) 无法为不透明的 return 值指定关联类型。因此,some IteratorProtocol 不足以让编译器确定 next() 方法 return.

应该使用什么样的值

如果您想实际使用序列,语言的这种限制会强制您显式声明迭代器类型。