
I am a Haskell beginner. I have used arrows occasionally to move 2-tuples around, but don't understand more than that. I'm interested in know what's the connection between arrows and 2-tuples. I don't really understand most of the Control.Arrow docs, but it seems that a lot of stuff about arrows doesn't mention 2-tuples. Yet the operators (***), (&&&), first, and second seem to be common. Is there some way to explain the link? Also, the main instance of Arrow seems to be (->). There is also something about Kleisli monads, but I don't know what those are. Is there an another big use case for arrows besides (->)? Don't worry about explaining it all, just a quick mention would be fine and I can investigate it myself. D

On 02/16/2016 03:06 AM, Dennis Raddle wrote:
I am a Haskell beginner. I have used arrows occasionally to move 2-tuples around, but don't understand more than that.
I'm interested in know what's the connection between arrows and 2-tuples. I don't really understand most of the Control.Arrow docs, but it seems that a lot of stuff about arrows doesn't mention 2-tuples. Yet the operators (***), (&&&), first, and second seem to be common. Is there some way to explain the link?
Also, the main instance of Arrow seems to be (->). There is also something about Kleisli monads, but I don't know what those are. Is there an another big use case for arrows besides (->)? Don't worry about explaining it all, just a quick mention would be fine and I can investigate it myself.
An arrow is basically a function and it doesn't hurt to think of them that way. In mathematics, "function" means something very specific, so they needed a new name (arrow) for a thing that's a lot like a function but isn't one. You can construct some weird situations where arrows aren't very much like mathematical functions at all, but it still doesn't hurt to think of them that way. Mentally I prefer to embiggen my concept of "function" rather than give it up entirely in the new setting. You're probably already used to this: the random() "function" is not a mathematical function, but we all call it one. There's no specific connection between arrows and two-tuples. It's extremely common to use functions on two-tuples, and every function is an arrow, so the fact that all of those useful (***) and (&&&) live in Control.Arrow is a bit of a premature abstraction. Frequently you'll need to take a function f and a pair (x,y) and want to compute the pair (f x, f y). There should really be a combinator for that! But when you write one, it turns out that it works just as well for arrows. Since all functions are arrows, they just used the more general type. The Kleisli arrow/monad thing isn't wrong, it's just useless without an example. Kleisli arrows are just plain old arrows (think: functions) in a monad. Suppose I want to read a file and then print its contents to the screen. How would I do that? In pseudo-code, it's something like, -- Read a file and print its contents to the screen (putStr . readFile) "/path/to/file.txt" But here, "print" and "readFile" aren't mathematical functions, so we can't compose them! The "." operator only works on functions. It would be great if there were something that was a lot like a function but could be composed in this manner... -- Read a file and print its contents to the screen ghci> import Control.Monad ( (<=<) ) ghci> (putStr <=< readFile) "hw.txt" Hello, world! Another useful example is when you want to "automatically" concatenate a list of results. Let's write a stupid function that duplicates its argument in a list: ghci> let twice x = [x, x] ghci> twice 3 [3,3] So far so good. But now I want four things. Can I compose "twice" with itself? ghci> (twice . twice) 3 [[3,3],[3,3]] ghci> :t (twice . twice) (twice . twice) :: t -> [[t]] Crap, that's giving me a list of lists. I just want one list! By thinking of "twice" as a multi-valued function (a special type of arrow), I can get what I want: ghci> (twice <=< twice) 3 [3,3,3,3] That trick is using the Monad instance for lists, but composition in monads is done with arrows (not mathematical functions). It's put to good use in e.g. HXT where you can say "give me all children of <p> elements that live in a <div> that live in a <body>" and you only want one list back. Without that funny arrow composition, you'd be stuck with lists of lists of lists of lists...

Thank you, this is great. I notice that none of your monad examples import
Control.Arrow. The composition operators come from Control.Monad, right? So
it's correct to call putStr etc. an arrow even though we never need to
actually use the word "arrow" to work with it or compose such "functions"?
D
On Tue, Feb 16, 2016 at 7:22 AM, Michael Orlitzky
On 02/16/2016 03:06 AM, Dennis Raddle wrote:
I am a Haskell beginner. I have used arrows occasionally to move 2-tuples around, but don't understand more than that.
I'm interested in know what's the connection between arrows and 2-tuples. I don't really understand most of the Control.Arrow docs, but it seems that a lot of stuff about arrows doesn't mention 2-tuples. Yet the operators (***), (&&&), first, and second seem to be common. Is there some way to explain the link?
Also, the main instance of Arrow seems to be (->). There is also something about Kleisli monads, but I don't know what those are. Is there an another big use case for arrows besides (->)? Don't worry about explaining it all, just a quick mention would be fine and I can investigate it myself.
An arrow is basically a function and it doesn't hurt to think of them that way. In mathematics, "function" means something very specific, so they needed a new name (arrow) for a thing that's a lot like a function but isn't one.
You can construct some weird situations where arrows aren't very much like mathematical functions at all, but it still doesn't hurt to think of them that way. Mentally I prefer to embiggen my concept of "function" rather than give it up entirely in the new setting. You're probably already used to this: the random() "function" is not a mathematical function, but we all call it one.
There's no specific connection between arrows and two-tuples. It's extremely common to use functions on two-tuples, and every function is an arrow, so the fact that all of those useful (***) and (&&&) live in Control.Arrow is a bit of a premature abstraction. Frequently you'll need to take a function f and a pair (x,y) and want to compute the pair (f x, f y). There should really be a combinator for that! But when you write one, it turns out that it works just as well for arrows. Since all functions are arrows, they just used the more general type.
The Kleisli arrow/monad thing isn't wrong, it's just useless without an example. Kleisli arrows are just plain old arrows (think: functions) in a monad. Suppose I want to read a file and then print its contents to the screen. How would I do that? In pseudo-code, it's something like,
-- Read a file and print its contents to the screen (putStr . readFile) "/path/to/file.txt"
But here, "print" and "readFile" aren't mathematical functions, so we can't compose them! The "." operator only works on functions. It would be great if there were something that was a lot like a function but could be composed in this manner...
-- Read a file and print its contents to the screen ghci> import Control.Monad ( (<=<) ) ghci> (putStr <=< readFile) "hw.txt" Hello, world!
Another useful example is when you want to "automatically" concatenate a list of results. Let's write a stupid function that duplicates its argument in a list:
ghci> let twice x = [x, x] ghci> twice 3 [3,3]
So far so good. But now I want four things. Can I compose "twice" with itself?
ghci> (twice . twice) 3 [[3,3],[3,3]] ghci> :t (twice . twice) (twice . twice) :: t -> [[t]]
Crap, that's giving me a list of lists. I just want one list! By thinking of "twice" as a multi-valued function (a special type of arrow), I can get what I want:
ghci> (twice <=< twice) 3 [3,3,3,3]
That trick is using the Monad instance for lists, but composition in monads is done with arrows (not mathematical functions). It's put to good use in e.g. HXT where you can say "give me all children of <p> elements that live in a <div> that live in a <body>" and you only want one list back. Without that funny arrow composition, you'd be stuck with lists of lists of lists of lists...
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

On 02/16/2016 04:11 PM, Dennis Raddle wrote:
Thank you, this is great. I notice that none of your monad examples import Control.Arrow. The composition operators come from Control.Monad, right? So it's correct to call putStr etc. an arrow even though we never need to actually use the word "arrow" to work with it or compose such "functions"?
Sure, they're just a special kind of arrow. My examples used (<=<) because otherwise you won't get the composition "in a monad" and it won't work the way it should: ghci> import Control.Arrow ( (<<<) ) ghci> let twice x = [x, x] ghci> (twice <<< twice) 3 [[3,3],[3,3]] "Why" is a little annoying. Basically, in Haskell, you can only make a structure an instance of a typeclass in one way. This gets in the way when there's more than one valid choice. For example, you might have, data Person = Person { firstname :: String, lastname :: String } Now if you want to display these, how would you do it? Here's one way: instance Show Person where -- FirstName LastName show p = (firstname p) ++ " " ++ (lastname p) But here's another: instance Show Person where -- Lastname, Firstname show p = (lastname p) ++ ", " ++ (firstname p) Which one is correct? They're equally valid... but you can only choose one. If I want both of them, I have to wrap Person in a newtype and then give that newtype a Show instance. Or another way would be to create a second typeclass (Show2?) that acts differently than Show. The same thing happens with these abstract algebraic structures. I can take the set {0, 1} and make it a group in two different ways, but in Haskell, I have to choose only one. What you're seeing with (<<<) versus (<=<) is just one of those choices. When you have a function like "twice", there's an obvious way to make it an arrow -- you define arrow composition to be function composition. In that way you can make every function an Arrow instance by default. But as you saw, there's actually a second and equally-valid way to define the (arrow) composition between things of the type a -> [a]. If you use "composition" from Arrow, you'll get the default function composition, but if you use "composition" from Monad, you'll get the second type. tl;dr if you want a useful example of arrows, you aren't going to get it by using (<<<) on regular functions because all you're going to get is regular function composition, and you already know how that's useful.
participants (2)
-
Dennis Raddle
-
Michael Orlitzky