Swift3:在通用扩展中进行类型推断

时间:2016-09-15 17:50:33

标签: arrays swift extension-methods concat swift3

我需要做这样的事情:

extension Array { 
    func flat() -> Element { return self.flatMap { $0 } }
}

但是类型推断存在问题:

  

' flatMap'生成' [SegmentOfResult.Iterator.Element]'而不是   预期的上下文结果类型'元素'

修改:使用示例:

[[1,2],[3,4,5],[6]].flat()

应该生成[1,2,3,4,5,6],它与:

相同
[[1,2],[3,4,5],[6]].flatMap { $0 }

1 个答案:

答案 0 :(得分:4)

如果你看一下flatMap(_:)签名,

extension Sequence {
    // ...
    public func flatMap<SegmentOfResult : Sequence>(_ transform: (Self.Iterator.Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element]
    // ...
}

你会看到它返回[SegmentOfResult.Iterator.Element],其中SegmentOfResult是从你传递它的函数返回的类型。这不一定与Element类型相同(因为您的扩展名是所有数组),这就是您的代码无法编译的原因。

为了处理元素为序列的数组,您需要约束扩展名以便Element : Sequence

此外,由于您传递给flatMap(_:)的函数是一个标识转换(它只返回它作为输入接收的元素),您需要将返回类型更改为[Element.Iterator.Element](内部元素的数组。)

extension Array where Element : Sequence {
    func flat() -> [Element.Iterator.Element] {
        return self.flatMap { $0 }
    }
}

尽管如此,我认为没有理由不将其作为Sequence的延伸:

// An extension for a sequence of sequences
extension Sequence where Iterator.Element : Sequence {

    // returns an array of the inner element type (an array of the element of the element)
    func flat() -> [Iterator.Element.Iterator.Element] { 
        return self.flatMap { $0 }
    }
}

(但是,我并不认为首先需要为此创建扩展名 - array.flatMap{$0}并不是很长!)