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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.