Swift 中的 flatMap 定义

Definition of flatMap in Swift

我正在研究仿函数monad。所以我知道仿函数使用 map 而 monad 使用 flatMap,而且 mapflatMap 的定义如下所示。

enum Box<T> {
    case some(T)
    case empty
}

extension Box {
    func map<U>(_ f: @escaping (T) -> U) -> Box<U> {
        // ...
    }
}

extension Box {
    func flatMap<U>(_ f: (T) -> Box<U>) -> Box<U> {
        // ...
    }
}

我完全明白那些正在使用不同的 f 参数(感谢 this article)。

然后,我只想检查OptionalResultArraymapflatMap的定义。因为我听说那些也是 monad。在 OptionalResult 中,定义看起来与上面的自定义 mapflatMap 相同。

但在 Array 中没有。

func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence

我现在有点困惑。因为我知道一个 monad 应用了一个 returns 包装值到包装值的函数,所以我期望 flatMap 的定义如下所示(绝对错误)。

func flatMap<T>(_ transform: (Element) throws -> [T]) rethrows -> [T]

但无论如何都不是。

我错过了什么吗?我误解的地方在哪里?

你在期待

func flatMap<T>(_ transform: (Element) throws -> Array<T>) rethrows -> Array<T>

对于 Array

如果你仔细观察,以上只是你发现的签名的一个特例,当SegmentOfResult == Array<T>.

Array 中的 flatMap 不仅适用于 SegmentOfResult == Array<T> 的情况,而且适用于 Sequence 的任何 SegmentOfResult

为什么?因为我们想定义函数,以便它们可以在尽可能多的类型上工作(即尽可能通用)。事实证明,如果函数映射到任何 SequenceflatMap 也可以工作。也就是说,它不依赖于函数 returns 特别是 Array 这一事实。它仅取决于函数 returns 某种 Sequence 的事实。如果您有兴趣,请查看 flatMap 是如何实现的 here

出于同样的原因,flatMap 不仅适用于 Array,它适用于任何符合 Sequence!

的类型