为Clojure映射和减少Monad ...... Juxt Monad怎么样?

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,现在,学习另一种句法形式太难了.我想我找到了一些可能相关的链接但对我来说太神秘了

请有人能说清楚!

khi*_*sen 9

你的例子不是monad.monad表示可组合的计算步骤.在琐碎的身份monad中,计算步骤只是表达式评估.在monad中,一步可能是成功或失败的表达.在序列monad中,step是一个表达式,它产生可变数量的结果(序列的元素).在作者monad中,计算步骤是表达式评估和日志输出的组合.在状态monad中,计算步骤涉及访问和/或修改一段可变状态.

在所有这些情况下,monad plumbery负责正确组合步骤.m结果函数打包"普通"值以适合单值计算方案,并且m-bind函数将一个计算步骤的结果馈送到下一个计算步骤.

在(map + ab)中,没有要组合的计算步骤.没有秩序的概念.它只是嵌套表达式评估.减少相同.