是否可以在 Clojure 中从 Haskell 执行 Reader Monad? [英] Is it possible to do the Reader Monad from Haskell in Clojure?

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

问题描述

我查看了 algo.monadsfluokitten 文档.我还通读了 Jim DueyKonrad Hinsen莱昂纳多·博尔赫斯.

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 的唯一参考是这个谷歌小组讨论.

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

我的问题是:是否可以执行 Clojure 中 Haskell 的 Reader Monad? 你能举个例子吗?

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.

使用 Readerm-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))))

通过这些函数,我们可以用algo.monads来定义Reader:

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 并不是绝对必要的.但是,它可以使事情更清晰,并使我们更接近 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.

askasks 让我们检查一下环境.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))))

有了这个,我们可以通过第二个例子:

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 所需的全部.

So, that's all it takes to make Reader.

这篇关于是否可以在 Clojure 中从 Haskell 执行 Reader Monad?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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