是否可以在Clojure的Haskell中为读者Monad做读者



我已经看了算法。我还阅读了Jim Duey,Konrad Hinsen和Leonardo Borges的Monad博客条目。

我可以在Clojure中找到读者Monad的唯一参考是该Google组讨论。

我的问题是:可以在clojure中的haskell读者monad吗?您能提供一个例子吗?

当然。Reader只是一个函数,可以从中获取环境并提取一些值。

使用Readerm-result获得了一些值,并产生一个忽略环境并返回该值的读者:

(defn reader-result
  [value]
  "Ignores environment, returns value"
  (fn [env]
    value))

m-bind带一个读取器和一个接受值并产生新读取器的函数f。然后,它结合了这些论点来生产一个新读者,该读者将初始读取器应用于环境,将其产生的值馈送到f以生成新的读者,然后将该读者应用于环境:

(defn reader-bind
  [reader f]
  "Applies reader to environment,
   then applies f to new environment"
  (fn [env]
    (let [read-value (reader env)]
      ((f read-value) env))))

使用这些功能,我们可以用algo.monads定义Reader

(m/defmonad Reader
          [m-result  reader-result
           m-bind    reader-bind])

有一些重要的辅助功能。run-reader带有读者和环境,并将读者应用于该环境:

(defn run-reader
  "Runs a reader against an environment,
   returns the resulting environment"
  [reader env]
  (reader env))

由于我们的读者只是功能,因此run-reader并非严格必要。但是,它可以使事情变得更加清晰,并且使我们更接近Haskell实施,因此我们将使用它进行。

askasks让我们检查环境。ask是返回环境的读者。asks采用选择器,并创建将选择器应用于环境的读取器:

(defn ask
  "A reader that returns the environment"
  [env]
  env)
(defn asks
  "A reader that returns the result of
   f applied to the environment"
  [f]
  (fn [env]
    (f env)))

这使我们足够远,可以通过第一个Reader示例:

(defn lookup-var
  [name bindings]
  (get bindings name))
(def calc-is-count-correct?
  (m/domonad Reader
             [binding-count    (asks #(lookup-var "count" %))
              bindings         ask]
             (= binding-count (count bindings))))
(defn is-count-correct?
  [bindings]
  (run-reader calc-is-count-correct? bindings))
(def sample-bindings {"count" 3, "1" 1, "b" 2})
(println
    (str "Count is correct for bindings " sample-bindings ": "
         (is-count-correct? sample-bindings)))

另一个重要的Reader功能是local。这采用了修改环境和读者的函数,并创建一个新的读者,该读者在将环境传递给原始读取器之前对环境进行修改:

(defn local
  [modify reader]
  "A reader that modifies the environment
   before calling the original reader"
  (fn [env]
    (run-reader reader (modify env))))

这样,我们可以浏览第二个示例:

(def calc-content-len
  (m/domonad Reader
             [content ask]
             (count content)))
(def calc-modified-content-len
  (local #(str "Prefix " %) calc-content-len))
(let [s "12345"
      modified-len  (run-reader calc-modified-content-len s)
      len           (run-reader calc-content-len s)]
  (println
    (str "Modified 's' length: " modified-len))
  (println
    (str "Original 's' length: " len)))

所以,这就是制作Reader

clojure中有一些很棒的例子:

  • clojure中的读者单调
  • clojure中的作家单人
  • clojure中的国家单子
  • clojure中的身份单子
  • 也许是Clojure中的单子
  • clojure中的任何一个单子

相关内容

  • 没有找到相关文章

最新更新