首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >双泛型数据结构上的flatMap是什么样子的?

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

Stack Overflow用户
提问于 2016-01-15 00:57:23
回答 1查看 282关注 0票数 0

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

代码语言:javascript
复制
struct Work<Input, Output> {
    let work: Input -> Output
}

这种类型表示可以接受Input并转换成所需的Output的工作。我想看看这个数据结构是否符合一些功能概念,比如函子还是单子。

函子

代码语言:javascript
复制
extension Work {
    func map<MoreOutput>(transform: Output -> MoreOutput) -> Work<Input, MoreOutput> {
        return Work<Input, MoreOutput> {
            return transform(self.work($0))
        }
    }
}

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

Monad

我很难考虑flatMap (或fold)函数对Work的定义。我唯一能想到的就是:

代码语言:javascript
复制
extension Work {
    func flatMap<MoreOutput>(transform: Work<Output, MoreOutput>) -> Work<Input, MoreOutput> {
        return Work<Input, MoreOutput> { input in
            return transform.work(self.work(input))
        }
    }
}

如果您在flatMap中查找Array的定义,它看起来如下(简化):

代码语言:javascript
复制
func flatMap(transform: (Element) -> T?) -> [T]

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

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

代码语言:javascript
复制
func flatMap<B>(f: A -> F<B>) -> F<B>

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

有人能给我解释一下这个区别吗?甚至可以在flatMap上定义一个“正确”的Work函数吗?还是Work不满足这些属性成为Monad?

** 编辑

谢谢phg给我这么多有用的信息。我试着做了Profunctor的定义:

使Work成为Profunctor

代码语言:javascript
复制
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)
        }
    }
}

你觉得这样对吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-15 16:14:09

这是:

代码语言:javascript
复制
func flatMap<B>(f: A -> F<B>) -> F<B>

是您希望flatMap看起来的样子;它是monad通常的“绑定”操作。专门处理第二个参数上的函数,您将得到所谓的读者单读

代码语言:javascript
复制
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($0)).work($0)
        }
    }
}

注意:实际上我不会说Swift,这段代码只是猜测--因此包含了Haskell的原作。请随时编辑一个修正的版本。

下面是另一个定义:

代码语言:javascript
复制
func flatMap(transform: (Element) -> T?) -> [T]

我想T?的意思是“可选的T”或“可空的T”。这不是我们通常所理解的一元函数,但它是相关的。事实上,关于这样的“广义的一个问题”,已经有了flatMaps。答案是,如果两个单模是相容的,即存在一个保持一元结构的单模态射F<A> -> G<A>,那么定义它是有意义的。

代码语言:javascript
复制
func wrappedFlatMap<B>(f: A -> F<B>) -> G<B>

这可能正是这里发生的“选项类型”和列表类型所发生的情况,在那里,态射在逻辑上是公正的。

代码语言:javascript
复制
Just x ~> [x]
Nothing ~> []
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34802632

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档