[Haskell-beginners] arrows and 2-tuples
Michael Orlitzky
michael at orlitzky.com
Tue Feb 16 23:19:05 UTC 2016
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.
More information about the Beginners
mailing list