问题描述
我看过和文档。我还通过,和。
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中?您能提供一个示例吗?
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吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!