I originally posted this in Stack
Overflow<http://stackoverflow.com/questions/19505334/clojure-algo-monad-strange-m-plus-behaviour-with-parser-m-why-is-second-m-plus>,
but realised I might get more response from the google group. Apologies for
duplication.

I'm seeing some issues using a parser monad created from the state monad
transformer.

I've written a full test case on the SO page outlining the issue, which is
that when I use m-plus for the combined monad, it always evaluates the
first 2 methods, even though it uses the return values from the first (if
it is valid), and any state changes in the second occur but are discarded
(however side effects do - like d/b updates etc).

e.g.

(def parser-m (state-t maybe-m))
(def world-destroyer
  (domonad parser-m
           [_ (fetch-state)
            result (m-plus
                    (check-we-are-chilled)
                    (destroy-planet))]
           result))
(world-destroyer {:chill-out true})

In this implementation, destroy-planet is always evaluated.
Both of these monadic functions can terminate by using a :when condition on
the state.

If I add a dummy method to the m-plus call list at the start (as first or
as second method in list) that does nothing (using a :when nil predicate to
stop its evaluation), the results are fine, no planet is destroyed because
it's never called, and the dummy monadic function takes the hit of stopping
m-plus spilling into the destroy-planet function.

Interestingly, any state changes I make in the method erroneously called do
not get reflected in the final return value (clearly due to immutability of
the state map), but side effects are happening - and that's my issue.

I've reverted to using a hand-crafted parser-m as given on Jim Duey's monad
blog <http://www.intensivesystems.net/tutorials/monads_101.html> which
doesn't exhibit this behaviour.

I'm relatively inexperienced with clojure and monads (I was using this as
an excuse to learn them both), so I thought i'd try and work out why it's
happening.

>From looking at the definitions of state-t monad-m, the only thing i can
see m-plus doing different to Jim's version is:

state-t monad-m:
(defn x [s]
  (apply (fn [& xs]
           (first (drop-while nil? xs)))
         (map #(% s) flist)))

jim's:
(defn y [s]
  (first (drop-while nil?
                     (map #(% s) flist))))

for some list of functions flist, e.g.
(def flist
  [(fn [x]
     (println "f a : " x)
     (when-let [r (:a x)] r))
   (fn [x]
     (println "f b: "x)
     (when-let [r (:b x)] r))
   (fn [x]
     (println "f nil : " x)
     nil)])

(x {:b 2})
(y {:b 2})

and running either of these produces same result (2), however they both
produce the println side effects of *all 3* functions in the list, so now
i'm even more confused.

I thought everything in y is lazy, so only the first two methods would be
used from the array. I can't find anything saying apply is lazy, so thought
I was getting closer.

Anyone have any thoughts on this? Am I using m-plus in the right way inside
a domonad call?

Cheers,
Mark

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to