Map 映射并减少Clojure的Monad。。。那就来一杯Juxt Monad怎么样?
在学习Clojure的过程中,我花了很多时间试图理解单子——它们是什么以及我们如何使用它们。。。。没有太多的成功。然而,我发现了一个优秀的“蒙娜斯为傻瓜”视频系列——由布赖恩·马里克为Clojure制作 到目前为止,我对单子的理解是,它有点像宏,因为它允许以易于阅读的形式编写一组语句,但单子的形式要正式得多。我的观察仅限于两个例子: 1。身份单子(或“let”单子)取自 我们希望填写的表格为:Map 映射并减少Clojure的Monad。。。那就来一杯Juxt Monad怎么样?,map,clojure,monads,reduce,Map,Clojure,Monads,Reduce,在学习Clojure的过程中,我花了很多时间试图理解单子——它们是什么以及我们如何使用它们。。。。没有太多的成功。然而,我发现了一个优秀的“蒙娜斯为傻瓜”视频系列——由布赖恩·马里克为Clojure制作 到目前为止,我对单子的理解是,它有点像宏,因为它允许以易于阅读的形式编写一组语句,但单子的形式要正式得多。我的观察仅限于两个例子: 1。身份单子(或“let”单子)取自 我们希望填写的表格为: (let [a 1 b (inc a)] (* a b)) (for [a (r
(let [a 1
b (inc a)]
(* a b))
(for [a (range 5)
b (range a)]
(* a b))
对应的单子是
(domonad identity-m
[a 1
b (inc a)]
(* a b))
(domonad sequence-m
[a (range 5)
b (range a)]
(* a b))
2。单子序列(或“for”单子)取自
我们希望填写的表格是:
(let [a 1
b (inc a)]
(* a b))
(for [a (range 5)
b (range a)]
(* a b))
对应的单子是
(domonad identity-m
[a 1
b (inc a)]
(* a b))
(domonad sequence-m
[a (range 5)
b (range a)]
(* a b))
Clojure中的单子定义
查看源代码,使用clojure monads库-:
同一性单子:
user=> (source identity-m)
(defmonad identity-m
[m-result identity
m-bind (fn m-result-id [mv f]
(f mv))
])
序列单体:
user=> (source sequence-m)
(defmonad sequence-m
[m-result (fn m-result-sequence [v]
(list v))
m-bind (fn m-bind-sequence [mv f]
(flatten* (map f mv)))
m-zero (list)
m-plus (fn m-plus-sequence [& mvs]
(flatten* mvs))
])
所以我的结论是,monad是一种广义的高阶函数,它接受一个输入函数和输入值,添加自己的控制逻辑,并吐出一个可以在“domonad”块中使用的“东西”
问题1
最后,对于问题:我想学习如何编写monad,并说我想编写一个模仿clojure中“map”形式的“map monad”:
(domonad map-m
[a [1 2 3 4 5]
b [5 6 7 8 9]]
(+ a b))
应该相当于
(map + [1 2 3 4 5] [5 6 7 8 9])
并返回值
[6 8 10 12 14]
如果我看一下源代码,它会给我类似于identity-m和sequence-m的东西:
user=> (source map-m)
(defmonad map-m
[m-result ...
m-bind ...
m-zero ...
m-plus ...
])
问题2
我还希望能够定义“reduce-m”,这样我就可以写:
(domonad reduce-m
[a [1 2 3 4 5]]
(* a))
这可能会给我1 x 2 x 3 x 4 x 5=120或
(domonad reduce-m
[a [1 2 3 4 5]
b [1 2 3 4 5]]
(+ a b))
给我(1+2+3+4+5)+(1+2+3+4+5)=30
最后
我是否也能够编写一个模仿juxt函数的“juxt monad”,但不是为绑定传递值,而是传递一组函数:
(domonad juxt-m
[a #(+ % 1)
b #(* % 2)]
'([1 2 3 4 5] b a) )
给予
可能,我可以用宏完成所有这些事情,所以我真的不知道这些“单子”有多有用,或者它们是否被认为是“单子”。。。有了互联网上的所有资源,在我看来,如果我想正确地学习单子,我必须学习Haskell,而现在,学习另一种句法形式太难了。我想我找到了一些可能相关的链接,但对我来说太神秘了
请有人给我点光 你的问题不是单子的类型。它们看起来更像是一种语法糖,你可以使用宏来完成,我甚至不建议你这样做,因为map、reduce等都是简单的函数,没有必要让它们的界面复杂化 之所以这些情况不是单子,是因为单子是一种放大值,包裹正常值。在map和reduce的情况下,您使用的向量不需要放大就可以在map或reduce中工作 尝试在domoand表达式上进行macroexpand将对您有所帮助。 例如:sequence monad示例应扩展为:
(bind (result (range 5))
(fn [a]
(bind (result (range a))
(fn [b] (* a b))
)))
其中bind和result是序列monad m-bind和m-result中定义的函数。
因此,基本上,domand后面的向量表达式被嵌套,向量后面的表达式被按原样使用,在上述情况下(*ab)被按原样调用(只是a和b值由monad提供)。在您的map monad示例中,向量表达式应该是原样的,最后一个表达式(+ab)应该以某种方式表示(map+ab),这不是monad应该做的。我找到了一些非常好的monad资源:
- (吉姆·杜伊(Jim Duey)的《单子指南》(monad Guide),该指南真正深入了单子的基本定义)
- (一大堆单子上的论文)
- (关于范畴理论的演讲,我只听了一半)
在本文中,他给出了一个单子,它将集合作为输入,而不是列表。将完成所有示例…您的示例不是单子。单子表示可组合的计算步骤。在平凡的恒等式单子中,计算步骤只是一个表达式求值 在maybe monad中,步骤是一个可能成功或失败的表达式 在序列monad中,step是一个表达式,它生成数量可变的结果(序列的元素) 在作者monad中,计算步骤