1

このチュートリアルを見た後、私自身の例のいくつかに取り組んでいます。 sigfpe.com/2006/08/you-could-have-invented-monads-and.html .

私は次の機能を思い付きました:

(定義単位 [vs]
  (fn [] [vs]))

(defn bind [mv f]
  (f (mv)))

(defn inc+ [mv]
  (練る
   mv
   (fn [[vs]]
     (let [r (inc v)]
       (ユニット r (適用 str (concat s " inc+(" (str r) ")")))))))

(defn double+ [mv]
  (練る
   mv
   (fn [[vs]]
     (let [r (* 2 v)]
       (ユニット r (適用 str (concat s " double+(" (str r) ")"))))))

(defn triple+ [mv]
  (練る
   mv
   (fn [[vs]]
     (let [r (* 3 v)]
       (ユニット r (適用 str (concat s " triple+(" (str r) ")")))))))

;; テスト:

((-> (ユニット 1 "1 ->") inc+))
;; => [2 "1 -> inc+(2)"]


((-> (ユニット 3 "3 ->") inc+ double+ inc+))
;; => [27 "3 -> inc+(4) double+(8) inc+(9) triple+(27)"]

メソッド inc+ double+ および triple+ のパターンをカプセル化するように bind を書き直して、以前と同じ出力を得たいと考えています。これはどのように行われますか?

4

1 に答える 1

1

私はそれを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を見ると、核となる原則を理解していると思います。「モナド」とは、手元にある関数を再利用できるようにすることです。連携するように設計する必要がありますunitbind次に、関数を一緒に構成するのはほとんど簡単です。

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ください。binddo-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)"]
于 2012-09-08T00:38:48.633 に答える