Это разумная монада для изменчивого состояния в Clojure? - PullRequest
1 голос
/ 20 октября 2010

Я экспериментировал с монадами в Clojure и придумал следующий код, где пара монадическое значение / состояние представлена ​​изменяемым объектом типа Clojure.

Поскольку объект является изменяемым, может показаться преимуществом то, что вы можете писать монадический код без необходимости все время создавать новые объекты результатов.

Тем не менее, я довольно новичок в монадах, поэтому хотел бы знать:

  • Имеет ли эта конструкция смысл?
  • Будет ли он действительно работать как монада?

Код ниже:

(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>

1 Ответ

3 голосов
/ 23 октября 2010

Нет, он не будет работать как монада, потому что вы используете изменяемое состояние.

Представьте, что у вас есть монадическое значение m (значение, содержащее состояние), которое вы называетеStateStore.Вы хотите быть в состоянии сделать это:

(let
   [a (incr-state m)
    b (decr-state m)]
  (if some-condition a b))

Я ожидаю, что это вычисление вернет монадический m, состояние которого было, согласно some-condition, увеличено или уменьшено.Если вы используете изменяемое состояние, оно будет и увеличиваться и уменьшаться во время оценки этого кода.

Одна из хороших особенностей монад заключается в том, что, хотя они представляют эффекты, они ведут себя как обычные чистые, неизменяемые значения.Вы можете передавать их, дублировать (вы можете расширить любое определение let монадического значения, заменив его имя определением на каждом сайте использования).Единственное место, где вы должны быть осторожны, это где вы на самом деле цепочка эффект, используя m-bind.В противном случае не существует неявного связывания эффектов в несвязанных частях кода, как в обычном императивном программировании.Это то, что делает рассуждения о монадах проще и удобнее в ситуациях, когда вы хотите ограничить побочные эффекты.

Редактировать

Возможно, вы слышали о монадических законах , которые являются уравнениями, которые должна соблюдать любая реализация монады.Однако ваша проблема здесь не в том, что вы нарушаете закон, поскольку закон не говорит об этом.Действительно, монадические законы обычно изложены на чистом языке Хаскелла, и поэтому не учитывают побочные эффекты.

Если вы хотите, вы можете рассматривать его как четвертый, невысказанный, монадический закон: хорошие монады должны уважать ссылочная прозрачность

...