我有以下(简单)数据结构:
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))
}
}
}
就我所知,这似乎是正确的。我能够编写一个地图函数,可以将Work<Input, Output>
转换为Work<Input, MoreOutput>
单子
我无法考虑flatMap
的{{1}}(或fold
)函数的定义。我能想出的唯一一件事就是:
Work
如果你在swift中查找extension Work {
func flatMap<MoreOutput>(transform: Work<Output, MoreOutput>) -> Work<Input, MoreOutput> {
return Work<Input, MoreOutput> { input in
return transform.work(self.work(input))
}
}
}
的{{1}}定义,它看起来像这样(简化):
flatMap
这是一个函数,其参数是一个函数,它将Array
转换为func flatMap(transform: (Element) -> T?) -> [T]
并生成Element
。我想不出将其抽象为T
类型的方法。
从另一本功能书中我发现了flatMap的一般定义如下(在一个对象Array
上持有Work
}:
F
A
的定义与func flatMap<B>(f: A -> F<B>) -> F<B>
似乎不同。
有人可以向我解释这个差异吗?甚至可以定义一个正确的&#39; flatMap
上的Array
功能?或flatMap
不满足Monad属性?
** 修改
感谢phg提供了这么多有用的信息。我尝试过Profunctor定义:
使Work
成为Work
:
Work
这看起来对你好吗?
答案 0 :(得分:1)
此:
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?
意味着&#34;可选T
&#34;或者&#34;可以为T
&#34;。这不是我们通常所理解的monadic函数,但它是相关的。事实上,a question关于这种&#34;广义的flatMaps&#34;。答案是,如果两个monad是兼容的,即存在 monad morphism F<A> -> G<A>
保留monadic结构,那么定义
func wrappedFlatMap<B>(f: A -> F<B>) -> G<B>
这可能就是&#34;选项类型&#34;正好发生的事情。和列表类型,其中态射在逻辑上只是
Just x ~> [x]
Nothing ~> []