
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.