It sounds like you're running into the chunked sequence behavior of
map (it's lazy but it realizes chunks of the sequence for efficiency
rather than strictly on-demand).

I'd say the possibilities are: don't use side-effecting functions in
your monads or define a fully lazy version of map and define m-plus in
terms of that?

Sean

On Tue, Oct 22, 2013 at 4:23 AM, Mark Fisher <mark.j.fis...@gmail.com> wrote:
> I originally posted this in Stack Overflow, 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 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.



-- 
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)

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