这个do-monad可以用let块代替吗?

时间:2015-03-10 10:32:46

标签: clojure monads let

使用do-monad的author here provides以下示例用法来组合测试生成器:

(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]...

commentator here asserts这是monad的一个很好的例子,不仅仅是为了它们自己,而是为了提供真正的增值。

对我而言,这似乎与let-block的作用不同。确实 - Brian Marick here compares the对mon阻止做了monad。

我的问题是:这可以用let块代替吗?

2 个答案:

答案 0 :(得分:1)

test.check的上下文中,答案为,此do-monad无法由let块替换。但您可以像这样手动使用gen/bindgen/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 [v e]))))))))

这就是Monad为您做的幕后工作。

尝试将其写为let

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

不起作用,因为功能:choosevectorelements会返回生成器,而不是生成器的结果。例如,gen/vector期望Integer作为第二个参数而不是generator,而let甚至无法编译。

答案 1 :(得分:0)

从test.check XDocument.Save(FolderBrowserDialog.SelectedPath + "\\" + "document.xml") 开始,有一个支持此类事情的宏0.9.0