在Clojure可以做Haskell的Reader Monad吗? [英] Is it possible to do the Reader Monad from Haskell in Clojure?

查看:122
本文介绍了在Clojure可以做Haskell的Reader Monad吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过 algo.monads floluitten 文档。我还通过 Jim Duey Konrad Hinsen Leonardo Borges

I've had a look at the algo.monads and fluokitten documentation. I've also read through monad blog entries by Jim Duey, Konrad Hinsen and Leonardo Borges.

我可以在Clojure的Reader Monad找到的唯一参考是这个google群组讨论

The only reference I can find to the Reader Monad in Clojure is this google groups discussion.

我的问题是:可以执行 Haskell中的阅读器Monad 在Clojure中?您能提供一个示例吗?

My question is: Is it possible to do the Reader Monad from Haskell in Clojure? Could you provide an example?

推荐答案

当然。 Reader 只是一个需要环境并从中提取一些值的函数。

Sure. A Reader is just a function that takes an environment and extracts some value from it.

c> Reader , m-result 需要一些值,并产生一个忽略环境并返回该值的读者:

With Reader, m-result takes some value and produces a reader that ignores the environment and returns that value:

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

m-bind 使用读取器和接受值并产生新读取器的函数 f 。然后将这些参数组合起来,产生一个新的读取器,将初始读取器应用于环境,将其产生的值馈送到 f 以产生新的读取器,然后将该读取器应用于环境:

m-bind takes a reader and a function f that accepts a value and produces a new reader. It then combines those arguments to produce a new reader which applies the initial reader to an environment, feeds the value it produces to f to produce a new reader, then applies that reader to the environment:

(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))))

使用这些函数,我们可以定义 Reader algo.monads

With these functions, we can define Reader with algo.monads:

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

有一些重要的帮助函数。 run-reader 需要读者和环境,并将读者应用于该环境:

There are a few important helper functions. run-reader takes a reader and environment and applies the reader to that environment:

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

由于我们的读者只是函数, run-reader isn' t严格必要。但是,它可以使事情更清楚,它使我们更接近Haskell实现,所以我们将使用它继续。

Since our readers are just functions, run-reader isn't strictly necessary. However, it can make things clearer and it keeps us closer to the Haskell implementation, so we'll use it going ahead.

code>和 asks 让我们检查环境。 ask 是返回环境的读者。 asks 接受选择器并创建一个将该选择器应用到环境的读取器:

ask and asks let us examine the environment. ask is a reader that returns the environment. asks takes a selector and creates a reader that applies that selector to an environment:

(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)))

这让我们足够深入了解第一阅读器示例

This gets us far enough to go through the first Reader example:

(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 。这需要修改环境和读取器的功能,并创建一个新的读取器,在将其传递给原始读取器之前修改环境:

The other important Reader function is local. This takes a function that modifies an environment and a reader and creates a new reader that modifies the environment before passing it to the original reader:

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

http://hackage.haskell.org/package/mtl-1.1.0.2/docs/Control-Monad-Reader.html#2\">第二个示例:

With that, we can go through the second example:

(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可以做Haskell的Reader Monad吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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