Sunday, May 17, 2009

Solutions to Chapter 6

(Yes, I know I've skipped Chapter 5. It was a bit too boring; I might return to it later.)

#1. Whoa, isn't this a bit early for that? You can understand what second does by reading the previous example with great care, and trying to understand what it should do. The tricky part here is that Control.Arrow introduces the Arrow class, which acts just like Haskell's syntactical arrow: "->".

Let's use ghci to find out second's type:

Prelude> :module Control.Arrow
Prelude Control.Arrow> :type second
second :: (Arrow a) => a b c -> a (d, b) (d, c)

Definitely confusing. But let's replace a, of class Arrow, with a "simple" arrow:

second :: (->) b c -> (->) (d, b) (d, c)

(I've underlined the changes to make reading easier.) Moving to infix notation (think of "arrow" as an operator), we get:

second :: b -> c -> (d, b) -> (d, c)

This clarifies everything (really!). The first argument is a function, from type b to type c. The second argument is a pair: a d and a b. The function second can't really do anything with the d: it knows nothing about the type. But it can convert the b to a c, using the b->c function which is the first argument. And indeed, the result is a d (the first part of the second argument, unmodified) and a c (the second part of the second argument, after we've applied the function to it).

Confusing? Let's see this in action:

Prelude Control.Arrow> second head ("hello","world")
("hello",'w')
Prelude Control.Arrow> second tail ("hello","world")
("hello","orld")
Prelude Control.Arrow> second (head.tail.tail) ("hello","world")
("hello",'r')
Prelude Control.Arrow> second (+1) (10,20)
(10,21)

In all cases, the function provided is applied to the second element of the pair, while the first element is left untouched.

#2. To find something's type, just ask ghci:

Prelude> :type (,)
(,) :: a -> b -> (a, b)
Prelude> :type (,,)
(,,) :: a -> b -> c -> (a, b, c)

So these are operators that build tuples.

No comments:

Post a Comment