双泛型数据结构上的 flatMap 是什么样子的?

How does a flatMap on a double-generic data-structure looks like?

我有以下(简单的)数据结构:

struct Work<Input, Output> {
    let work: Input -> Output
}

此类型表示可以将 Input 转化为所需 Output 的作品。我想看看这个数据结构是否符合一些函数概念,比如函子或 monad。

函子

extension Work {
    func map<MoreOutput>(transform: Output -> MoreOutput) -> Work<Input, MoreOutput> {
        return Work<Input, MoreOutput> {
            return transform(self.work([=11=]))
        }
    }
}

据我所知,这似乎是正确的。我能够编写一个映射函数,它可以将 Work<Input, Output> 变成 Work<Input, MoreOutput>

单子

我很难想到WorkflatMap(或fold)函数的定义。我唯一能想到的是:

extension Work {
    func flatMap<MoreOutput>(transform: Work<Output, MoreOutput>) -> Work<Input, MoreOutput> {
        return Work<Input, MoreOutput> { input in
            return transform.work(self.work(input))
        }
    }
}

如果您在 swift 中查找 ArrayflatMap 定义,它看起来像这样(简化):

func flatMap(transform: (Element) -> T?) -> [T]

这是一个函数,其参数是将 Element 转换为 T 并生成 Array 的函数。我想不出一种方法将其抽象为 Work 类型。

我从另一本功能性书籍中找到了 flatMap 的一般定义如下(在持有类型 A 的对象 F 上):

func flatMap<B>(f: A -> F<B>) -> F<B>

flatMap 的定义似乎与 Array 的定义不同。

谁能给我解释一下这个区别?甚至可以在 Work 上定义 'correct' flatMap 函数吗?或者 Work 不满足成为 Monad 的属性?

** 编辑

感谢 phg 提供这么多有用的信息。我试过做 Profunctor 定义:

制作Work一个Profunctor:

extension Work {
    func diMap<A, B>(fa: A -> Input, fb: Output -> B) -> Work<A, B> {
        return Work<A, B> { arg in
            let input = fa(arg)
            let output = self.work(input)
            return fb(output)
        }
    }
}

你觉得这样对吗?

这个:

func flatMap<B>(f: A -> F<B>) -> F<B>

就是你想要flatMap的样子;这是 monad 通常的 "bind" operation. Specialized for functions over the second argument, you get the so-called Reader monad:

extension Work {
    func flatMap<MoreOutput>(g: Output -> Work<Input, MoreOutput>) -> Work<Input, MoreOutput> {
        // (Reader f) >>= g = Reader $ \x -> runReader (g (f x)) x
        return Work<Input, MoreOutput> {
            g(self.work([=11=])).work([=11=])
        }
    }
}

注意:我实际上不会说 Swift,这段代码只是猜测——因此包含 Haskell 原文。请随意编辑更正后的版本。


现在进入另一个定义:

func flatMap(transform: (Element) -> T?) -> [T]

我想 T? 的意思类似于 "optional T" 或 "nullable T"。这不是我们通常理解的monadic function,但它是相关的。的确,关于这样的"generalized flatMaps"已经有a question了。答案是,如果两个 monad 兼容,即存在 monad morphism F<A> -> G<A> 保留 monadic 结构,定义

是有意义的
func wrappedFlatMap<B>(f: A -> F<B>) -> G<B>

这可能正是 "option type" 和列表类型在这里发生的情况,其中态射在逻辑上只是

Just x ~> [x]
Nothing ~> []