私はそれを2段階で理解しました:
(定義単位 [vs]
(fn [] [vs]))
(defn bind [mv f]
(let [[iv is] (mv)
[av as] (f iv)]
(ユニット av (str は " " as))))
(defn inc+ [mv]
(練る
mv
(fn [v]
[(inc v) (str " inc+(" (inc v) ")")])))
(defn double+ [mv]
(練る
mv
(fn [v]
[(inc v) (str " double+(" (inc v) ")")])))
(defn triple+ [mv]
(練る
mv
(fn [v]
[(inc v) (str " triple+(" (inc v) ")")])))
それから:
(定義単位 [vs]
(fn [] [vs]))
(defn bind [mv f]
(let [[vs] (mv)
r (fv)
xs (->> (str (タイプ f))
(#"\$([^\$]*)\$?" を再検索)
2番目) ]
(単位 r (str s " " (str xs "(" r ")")))))
(defn inc+ [mv]
(bind mv inc))
(defn double+ [mv]
(バインド mv #(* 2 %)))
(defn triple+ [mv]
(バインド mv #(* 3 %)))
((-> (ユニット 3 "3 ->") inc+ double+ inc+ triple+))
;;=> [27 "3 -> inc_PLUS_(4) double_PLUS_(8) inc_PLUS_(9) triple_PLUS_(27)"]
したがって、他の Monad チュートリアル、特にhttp://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monadsを見ると、核となる原則を理解していると思います。「モナド」とは、手元にある関数を再利用できるようにすることです。連携するように設計する必要がありますunit
。bind
次に、関数を一緒に構成するのはほとんど簡単です。
do-m
次に、演算子を記述するためのもう 1 つの抽象化:
(定義単位 [vs]
(fn [] [vs]))
(defn bind [mv f]
(let [[vs] (mv)
r (fv)
xs (->> (str (タイプ f))
(#"\$([^\$]*)\$?" を再検索)
2番目) ]
(単位 r (str s " " (str xs "(" r ")")))))
(defn double [v] (* 2 v))
(定義トリプル [v] (* 3 v))
(defn do-m [v & fs]
(let [fn-ms (map #(fn [mv] (bind mv %)) fs)]
(((apply comp (reverse fn-ms)) (unit v (str v "->"))))))
(do-m 3 inc ダブル トリプル)
;;=> [24 "3 -> inc(4) double(8) triple(24)"]
これは、同じ結果を達成するための別の書き方です。変更は、 のラムダ関数と関連する および の呼び出しを削除することであることに注意してunit
ください。bind
do-m
(定義単位 [vs] [vs])
(defn bind [mv f]
(let [[vs] mv
r (fv)
xs (->> (str (タイプ f))
(#"\$([^\$]*)\$?" を再検索)
2番目) ]
(単位 r (str s " " (str xs "(" r ")")))))
(defn double [v] (* 2 v))
(定義トリプル [v] (* 3 v))
(defn sqrt [v] (数学/平方 v))
(defn do-m [v & fs]
(let [fn-ms (map #(fn [mv] (bind mv %)) fs)]
((apply comp (reverse fn-ms)) (unit v (str v " ->")))))
(do-m 3 inc double double triple triple sqrt)
;; => [12.0 "3 -> inc(4) double(8) double(16) triple(48) triple(144) sqrt(12.0)"]