[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