这个do-monad是否可以替换为let块? [英] Could this do-monad be replaced by a let block?

查看:88
本文介绍了这个do-monad是否可以替换为let块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里的作者提供以下内容do-monad组合测试生成器的示例用法:

 (require'[clojure.test.check.generators:as gen ])
(require'[clojure.algo.monads:as m])
(m / defmonad gen-m
[m-bind gen / bind
m-result gen / return])

(def vector-and-elem
(m / domonad gen-m
[n(gen / choose 1 10)
v vector gen / int n)
e(gen / element v)]
[v,e]))

(gen / sample vector-and-elem)
([[0 -1 1 0 -1 0 -1 1] 0]
[[1 1 3 3 3 -1 0 -2 2] 3]
[[8 4] 8] .. 。

这里的评论员断言,这是一个非常好的例子,不仅仅是为了自己,而是为了提供一个真正的增值。



<对我来说,这似乎没有什么不同于一个让块正在做什么。确实 -
Brian Marick 这里将 do-monad与let块进行比较。



我的问题是:这个do-monad是否可以替换为let块?

c> c> c> c> c> c> do-monad 不能被 let 块替换。但您可以像下面这样手动使用 gen / bind gen / return

 (def vector-and-elem 
(gen / bind(gen / choose 1 10)
(fn [n]
(gen / bind(gen / vector gen / int n)
(fn [v]
(gen / bind(gen / elements v)
(fn [e]
(gen / return [ve]))))))))

c $ c> Monad 正在为你做掩护。



尝试以 let 写:

 (def vector-and-elem-let 
(let [n(gen / choose 1 10)
v(gen / vector gen / int n)
e(gen / elements v)]
[ve]))

因为函数:选择向量元素返回a 因此,例如 gen / vector 期望一个 Integer 作为第二个参数而不是 code>并且 let 甚至不编译。


The author here provides the following example usage of a do-monad to combine test generators:

(require '[clojure.test.check.generators :as gen])
(require '[clojure.algo.monads :as m])
(m/defmonad gen-m 
  [m-bind gen/bind 
   m-result gen/return])

(def vector-and-elem
  (m/domonad gen-m
    [n (gen/choose 1 10)
     v (gen/vector gen/int n)
     e (gen/element v)]
    [v, e]))

(gen/sample vector-and-elem)
    ([[0 -1 1 0 -1 0 -1 1] 0] 
    [[1 1 3 3 3 -1 0 -2 2] 3]
    [[8 4] 8]...

There commentator here asserts that this is a great example of monads not just for their own sake, but for providing a genuine value-add.

To me this doesn't seem that different from what a let-block is doing. Indeed - Brian Marick here compares the do-monad to a let block.

My question is: Could this do-monad be replaced by a let block?

解决方案

In the context of test.check the answer is no, this do-monad can't be replaced by a let block. But you can use the gen/bind and gen/return manually like this:

(def vector-and-elem
  (gen/bind (gen/choose 1 10)
            (fn [n]
              (gen/bind (gen/vector gen/int n)
                        (fn [v]
                          (gen/bind (gen/elements v)
                                    (fn [e]
                                      (gen/return [v e]))))))))

This is what the Monad is doing under the covers for you.

Trying to write this as a let:

(def vector-and-elem-let
  (let [n (gen/choose 1 10)
        v (gen/vector gen/int n)
        e (gen/elements v)]
    [v e]))

Doesn't work because the functions: choose, vector, and elements returns a generator not the result of the generator. So for example gen/vector expects a Integer as the second argument not a generator and this let doesn't even compile.

这篇关于这个do-monad是否可以替换为let块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆