It's difficult to see how it's a chunked issue, the original code is just 
calling monadic functions, the only map is the state (the latter part of my 
post was an attempt to manually recreate what the monad macros are doing 
and I'm sure i didn't do a perfect job of it).

It's my understanding that the contract of m-plus is to return the results 
from the first function that returns non-nil. e.g. from 
http://onclojure.com/2009/03/23/a-monad-tutorial-for-clojure-programmers-part-3/
 
by Konrad Hinsen:

"m-plus is a function that combines the results of two or more computations 
into a single one. For the sequence monad, it is the concatenation of 
several sequences. For the maybe monad, it is a function that returns the 
first of its arguments that is not nil."

By which I wouldn't expect it to call the second function if the first was 
non-nil.

Also, in Jim Duey's 
http://www.intensivesystems.net/tutorials/monads_101.html, he says it 
similarly:

"Taking advantage of the fact that first, drop-while and map are all lazy, 
m-plus applies only as many parsers as it needs to in order to get a 
result. If no parsers succeed, a nil is returned."

I've reverted to using the parser definition in the last link, as it's all 
I need for now. I'd be wary of using the "state-t maybe-m" monad though in 
future as it doesn't seem to be working as i'd expect.

Mark

On Tuesday, 22 October 2013 20:26:44 UTC+1, Sean Corfield wrote:
>
> 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...@gmail.com<javascript:>> 
> 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 clo...@googlegroups.com<javascript:> 
> > Note that posts from new members are moderated - please be patient with 
> your 
> > first post. 
> > To unsubscribe from this group, send email to 
> > clojure+u...@googlegroups.com <javascript:> 
> > 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+u...@googlegroups.com <javascript:>. 
> > 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