zca*_*ate 6 monads reduce clojure map
在学习Clojure的同时,我花了很多时间试图理解monad - 它们是什么以及我们如何使用它们......并没有太多的成功.然而,我发现了一个出色的'Monads for Dummies'视频系列 - http://vimeo.com/20717301 - 作者:Brian Marik为Clojure
到目前为止,我对monad的理解是它有点像一个宏,它允许一组语句以易于阅读的形式编写 - 但monad更加正式化.我的观察仅限于两个例子:
1.身份Monad(或'let'monad)取自http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/
我们希望写的表格是:
(let [a 1
b (inc a)]
(* a b))
Run Code Online (Sandbox Code Playgroud)
和相应的monad是
(domonad identity-m
[a 1
b (inc a)]
(* a b))
Run Code Online (Sandbox Code Playgroud)
2.序列Monad(或'for'monad)取自http://onclojure.com/2009/03/06/a-monad-tutorial-for-clojure-programmers-part-2/
我们希望写的形式是:
(for [a (range 5)
b (range a)]
(* a b))
Run Code Online (Sandbox Code Playgroud)
和相应的monad是
(domonad sequence-m
[a (range 5)
b (range a)]
(* a b))
Run Code Online (Sandbox Code Playgroud)
Clojure中的Monad定义
查看源代码,使用clojure monads库 - https://github.com/clojure/algo.monads:
user=>(use 'clojure.algo.monads)
nil
Run Code Online (Sandbox Code Playgroud)
indent monad:
user=> (source identity-m)
(defmonad identity-m
[m-result identity
m-bind (fn m-result-id [mv f]
(f mv))
])
Run Code Online (Sandbox Code Playgroud)
序列monad:
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))
])
Run Code Online (Sandbox Code Playgroud)
所以我的结论是monad是某种广义的高阶函数,它接受输入函数和输入值,添加自己的控制逻辑并吐出可以在'domonad'中使用的'thing'块.
问题1
最后,问题是:我想学习如何写一个monad并说我想写一个'map monad'来模仿clojure中的'map'表单:
(domonad map-m
[a [1 2 3 4 5]
b [5 6 7 8 9]]
(+ a b))
Run Code Online (Sandbox Code Playgroud)
应该相当于
(map + [1 2 3 4 5] [5 6 7 8 9])
Run Code Online (Sandbox Code Playgroud)
并返回值
[6 8 10 12 14]
Run Code Online (Sandbox Code Playgroud)
如果我查看源代码,它应该给我类似于identity-m和sequence-m的东西:
user=> (source map-m)
(defmonad map-m
[m-result ...
m-bind ...
m-zero ...
m-plus ...
])
Run Code Online (Sandbox Code Playgroud)
问题2
我也希望能够定义'reduce-m'以便我可以写:
(domonad reduce-m
[a [1 2 3 4 5]]
(* a))
Run Code Online (Sandbox Code Playgroud)
这可能会给我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))
Run Code Online (Sandbox Code Playgroud)
会给我(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) )
Run Code Online (Sandbox Code Playgroud)
给
[ [2 2] [4 3] [6 4] [8 5] [9 6] ]
Run Code Online (Sandbox Code Playgroud)
潜在地,我可以用宏来做所有这些事情,所以我真的不知道这些'monads'会有多么有用,或者如果他们甚至被认为是'monad'......在互联网上的所有资源,在我看来如果我想要正确学习Monads,我必须学习Haskell,现在,学习另一种句法形式太难了.我想我找到了一些可能相关的链接但对我来说太神秘了
请有人能说清楚!
你的例子不是monad.monad表示可组合的计算步骤.在琐碎的身份monad中,计算步骤只是表达式评估.在monad中,一步可能是成功或失败的表达.在序列monad中,step是一个表达式,它产生可变数量的结果(序列的元素).在作者monad中,计算步骤是表达式评估和日志输出的组合.在状态monad中,计算步骤涉及访问和/或修改一段可变状态.
在所有这些情况下,monad plumbery负责正确组合步骤.m结果函数打包"普通"值以适合单值计算方案,并且m-bind函数将一个计算步骤的结果馈送到下一个计算步骤.
在(map + ab)中,没有要组合的计算步骤.没有秩序的概念.它只是嵌套表达式评估.减少相同.
| 归档时间: |
|
| 查看次数: |
1489 次 |
| 最近记录: |