- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下(简单)数据结构:
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($0))
}
}
}
据我所知,这似乎是正确的。我能够编写一个 map 函数,它可以将 Work<Input, Output>
进入Work<Input, MoreOutput>
单子(monad)
我很难想到 flatMap
的定义(或 fold
)函数 Work
。我唯一能想到的是:
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
的定义很快它看起来像这样(简化):
func flatMap(transform: (Element) -> T?) -> [T]
这是一个函数,其参数是一个转换 Element
的函数。进入T
结果是 Array
。我想不出一种方法可以将其抽象为 Work
类型。
从另一本功能书中,我找到了 flatMap 的一般定义,如下(在对象 F
持有类型 A
上):
func flatMap<B>(f: A -> F<B>) -> F<B>
这是 flatMap
的不同定义比Array
似乎实现了。
有人可以向我解释一下这种差异吗?是否有可能定义一个“正确”flatMap
功能于 Work
?或者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 。专门针对第二个参数的函数,您会得到所谓的 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($0)).work($0)
}
}
}
注意:我实际上不会说 Swift,这段代码只是猜测——因此包含了 Haskell 原始代码。请随意在更正的版本中进行编辑。
<小时/>现在来看另一个定义:
func flatMap(transform: (Element) -> T?) -> [T]
我想T?
意思是“可选 T
”或“可为空 T
”。这不是我们通常理解的一元函数,但它是相关的。确实,已经有a question关于这种“广义平面 map ”。答案是,如果两个单子(monad)兼容,即存在单子(monad)态射F<A> -> G<A>
保留一元结构,定义是有意义的
func wrappedFlatMap<B>(f: A -> F<B>) -> G<B>
这可能正是“选项类型”和列表类型所发生的情况,其中态射在逻辑上只是
Just x ~> [x]
Nothing ~> []
关于swift - 双泛型数据结构上的 flatMap 是什么样子的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34802632/
我是一名优秀的程序员,十分优秀!