我有以下(简单)数据结构:
struct Work<Input, Output> {
let work: Input -> Output
}这种类型表示可以接受Input并转换成所需的Output的工作。我想看看这个数据结构是否符合一些功能概念,比如函子还是单子。
函子
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的定义。我唯一能想到的就是:
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)
}
}
}你觉得这样对吗?
发布于 2016-01-15 16:14:09
这是:
func flatMap<B>(f: A -> F<B>) -> F<B>是您希望flatMap看起来的样子;它是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”。这不是我们通常所理解的一元函数,但它是相关的。事实上,关于这样的“广义的一个问题”,已经有了flatMaps。答案是,如果两个单模是相容的,即存在一个保持一元结构的单模态射F<A> -> G<A>,那么定义它是有意义的。
func wrappedFlatMap<B>(f: A -> F<B>) -> G<B>这可能正是这里发生的“选项类型”和列表类型所发生的情况,在那里,态射在逻辑上是公正的。
Just x ~> [x]
Nothing ~> []https://stackoverflow.com/questions/34802632
复制相似问题