<div class="gmail_quote"><div class="im"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>On Tue, Oct 12, 2010 at 8:56 AM, Uwe Schmidt <<a href="mailto:uwe@fh-wedel.de" target="_blank">uwe@fh-wedel.de</a>> wrote:<br>
>> No, but there is no point in using a formalism that adds complexity<br>
>> without adding functionality. Arrows are more awkward to use than<br>
>> monads because they were intentionally designed to be less powerful than<br>
>> monads in order to cover situations in which one could not use a monad.<br></div>
</blockquote><br></div>On Tue, Oct 12, 2010 at 9:49 AM, C. McCann <span dir="ltr"><<a href="mailto:cam@uptoisomorphism.net" target="_blank">cam@uptoisomorphism.net</a>></span> wrote<div class="im"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Essentially, arrows lend themselves best to composing first-order<br>
computations to create larger computations with a fixed structure. If<br>
you find yourself forced to frequently use ArrowApply or other means<br>
of eliminating higher-order structure--e.g., anything that results in<br>
an arrow with an output type that contains fewer instances of the<br>
arrow's own type constructor than does the input type--it may be worth<br>
considering if arrows are really what you want to use.<br>
<br>
Personally, though, I think monads are really overkill in many cases<br>
and strongly prefer, where possible, to use Applicative or Arrow.<br>
<br>
</blockquote></div></div><br>Well I am compelled to add my two cents
worth to this conversation. I like to use examples, so that is what I
will do. I am going to use a simple one, and you may wonder why I used
an arrow to represent this little computation, but the main reason is
that it fits the way I think better then if's , guards, cases, in or
where clauses. The entirety of a computation is right there in my
face. The other thing that I will explain after showing this little
example function {arrow under the hood} is that it leads to more
thinking of composing into even more higher orderness, until you have a
single function definition that can be the entire program. <br>
<br>Function splitMiddle: <br> Takes a list and returns a pair consisting of the<br> list split into two equal parts.<br><br>splitMiddle :: forall a. [a] -> ([a], [a])<br>splitMiddle =<br> (id &&& (length >>> flip div 2)) >>><br>
(\(xs,a) -> splitAt a xs)<br><br>usage:<br> splitMiddle [1..10]<br>([1,2,3,4,5],[6,7,8,9,10])<br><br>OKAY here is where the thoughts can come in to play and are a direct <br>result of the pointfree style that is adopted as a direct result of using arrow<br>
notation. To split the list of words of a line of text you may do this initially:<br><br>splitMiddle $ words "Now is the time to come to the aid of our country"<br>(["Now","is","the","time","to","come"],["to","the","aid","of","our","country"])<br>
<br>Then it occurs that well hell, why not move the "words" function into the arrow:<br><br>(words >>> splitMiddle) "Now is the time to come to the aid of our country"<br>(["Now","is","the","time","to","come"],["to","the","aid","of","our","country"])<br>
<br>That can be turned into a new function with great ease and clarity:<br><br>splitSentence :: String -> ([String], [String])<br>splitSentence = words >>> splitMiddle<br> <br>Then maybe I decide, hey, I only want the second half of the sentence:<br>
<br>sndHalfSentence :: String -> [String]<br>sndHalfSentence = words >>> splitMiddle >>> snd<br><br>or if I have defined splitSentence as above:<br><br>sndHalfSentence :: String -> [String]<br>sndHalfSentence = splitSentence >>> snd<br>
<br>doing the function fstHalfSentence is obvious in that the mechanics<br>are right there to see and no variables to muck it up, just change the <br>snd to fst :<br><br>fstHalfSentence :: String -> [String]<br>
fstHalfSentence = splitSentence >>> fst<br><br>The other nice use of arrow is INSIDE of a monadic structure:<br><br><br> "Now is the time to come to the aid of our country" >>= (return >>> words >>> concat)<br>
"Nowisthetimetocometotheaidofourcountry"<br><br>which can become the definition of squeeze:<br><br>squeeze :: [Char] -> [Char]<br>*Big3> let squeeze cs = cs >>= (return >>> words >>> concat)<br>
<br>squeeze "Now is the time to come to the aid of our country"<br>"Nowisthetimetocometotheaidofourcountry"<br><br>and then of course you can do a few sentences instead of only<br>one,if you change the definition with the simple addition of an <br>
<br>applicative operator to the mix.<br><br>squeezeSentenceF<br> :: forall (f :: * -> *). (Functor f) => f [Char] -> f [Char]<br>squeezeSentenceF css = (squeeze <$>) css<br>squeezeSentenceF ["This is how to do a list of sentences",<br>
"It makes use of applicatives too"]<br>["Thisishowtodoalistofsentences","Itmakesuseofapplicativestoo"]<br><br>notice that this is more general then just mapping as it applies to any<br>
functor, of which the Maybe monad has an instance..<br>so:<br> squeezeSentenceL (Just "This is how to do a Maybe sentence")<br>Just "ThisishowtodoaMaybesentence"<br><br>works just nicely. I think that the more you mix and match ALL of the tools and<br>
do a little experimentation with them, that it then begins to be a situation where <br>your thoughts of how to compose things are not locked down to one way and it<br>opens up your mind to many possibilities. I am a proponent of having and using<br>
ALL the available tools in a mix and match way if need be. About the only thing<br>you have to do to use any of the various tools in the same line of code is to remember<br>to use a parenthetic bit of separation between one and the next.<br>
metacode"<br>xss >>= ( ((g >>> h) <$>)
>>> return) so you are using a monadic bind to shove something
of {functor f, monad m} embodied in xss such that f (m x) has the <br>functions g and then h applied to the elements of the monad 'm' inside of the <br>
functor f and then have that structure returned as: f (m ((g>>>f) x)). <br><br>Okay, I am totally done with that.. probably just muddied things up, but maybe <br>make sense if you try using ghci after loading a dummy module that imports<br>
Control.Monad, Control.Arrow and Control.Applicative. I just think that one is <br>missing out when not using ALL the computational tools. <br><br>cheers,<br><font color="#888888">gene<br><br></font>