私はClojureでモナドを実験していて、次のコードを思いつきました。ここで、モナドの値と状態のペアは、可変のClojuredeftypeオブジェクトで表されます。
オブジェクトは変更可能であるため、常に新しい結果オブジェクトを作成しなくても、モナディックコードを記述できるという利点があるように思われます。
しかし、私はモナドにかなり慣れていないので、知りたいです:
- この構成は意味がありますか?
- それは実際にモナドとして正しく機能しますか?
以下のコード:
(defprotocol PStateStore
(set-store-state [ss v])
(get-store-state [ss])
(set-store-value [ss v])
(get-store-value [ss]))
(deftype StateStore [^{:unsynchronized-mutable true} value
^{:unsynchronized-mutable true} state]
PStateStore
(get-store-state [ss] (.state ss))
(get-store-value [ss] (.value ss))
(set-store-state [ss v] (set! state v))
(set-store-value [ss v] (set! value v))
Object
(toString [ss] (str "value=" (.value ss) ", state=" (.state ss))))
(defn state-store [v s] (StateStore. v s))
(defmonad MStoredState
[m-result (fn [v]
(fn [^StateStore ss]
(do
(set-store-value ss v)
ss)))
m-bind (fn [a f]
(fn [^StateStore ss]
(do
(a ss)
((f (get-store-value ss)) ss))))])
; Usage examples
(def mb
(domonad MStoredState
[a (m-result 1)
b (m-result 5)]
(+ a b)))
(def ssa (state-store 100 101))
(mb ssa)
; => #<StateStore value=6, state=101>