简体   繁体   English

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

[英]Swift3: type inference inside generic extension

I need to do something like this: 我需要做这样的事情:

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

But there is problem with type inference: 但类型推断存在问题:

'flatMap' produces '[SegmentOfResult.Iterator.Element]', not the expected contextual result type 'Element' 'flatMap'产生'[SegmentOfResult.Iterator.Element]',而不是预期的上下文结果类型'Element'

Edit: Usage example: 编辑:用法示例:

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

should produce [1,2,3,4,5,6] which is the same as: 应该产生[1,2,3,4,5,6] ,它与:

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

If you take a look at the flatMap(_:) signature, 如果你看一下flatMap(_:)签名,

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

you'll see that it returns a [SegmentOfResult.Iterator.Element] , where SegmentOfResult is the type that is returned from the function you pass it. 你会看到它返回一个[SegmentOfResult.Iterator.Element] ,其中SegmentOfResult是从你传递它的函数返回的类型。 This isn't necessarily the same type as Element (as your extension is for all arrays), which is why your code fails to compile. 这不一定是与Element相同的类型(因为您的扩展适用于所有数组),这就是您的代码无法编译的原因。

In order to be working with arrays where the elements are sequences, you'll want to constrain your extension so that Element : Sequence . 为了使用元素为序列的数组,您需要约束扩展以使Element : Sequence

Also, as the function you're passing to flatMap(_:) is an identity transform (it just returns the element it receives as input), you'll want to change the return type to [Element.Iterator.Element] (an array of the inner element). 此外,由于您传递给flatMap(_:)的函数是一个标识转换(它只返回它作为输入接收的元素),您需要将返回类型更改为[Element.Iterator.Element] (内部元素的数组)。

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

Although that being said, I see no reason why this shouldn't be an extension of Sequence : 虽然如此,但我认为没有理由不应该将这个Sequence作为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 }
    }
}

(However, I don't really see the need to create an extension for this in the first place – array.flatMap{$0} isn't exactly lengthy!) (但是,我并不认为首先需要为此创建扩展 - array.flatMap{$0}并不是很长!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM