[Haskell-beginners] Type classes and synonyms

Felipe Lessa felipe.lessa at gmail.com
Sat Nov 21 16:08:33 EST 2009


On Sat, Nov 21, 2009 at 08:33:28PM +0000, Philip Scott wrote:
> Righto, I am getting stuck in with that. One last question; I've been trying
> to read up on Arrows and my mind is being boggled. Via experiment, I have
> worked out what 'second' was doing (the documentation is useless unless you
> already understand a lot of stuff I clearly don't)
>
> For the other newbies, 'second' takes a function and a tuple, it applies the
> function to the second thing in your tuple and returns a tuple with the first
> value unchanged, and the result of applying 'f' to the second:
>
> >  second (\x -> "fish") (10,20)
> (10,"fish")
>
> What I am struggling to understand is what on earth the type signature means:
>
> :t second
> second :: (Arrow a) => a b c -> a (d, b) (d, c)
>
> How can (\x -> "fish") be an 'a b c' when it really looks like this:
>
> :t (\x->"fish")
> (\x->"fish") :: t -> [Char]
>
> And I am pretty sure I never made any Arrpws...
>
> I feel I am on the verge of understanding something deep and fundamentally
> philosophical about the typesystem but I can't quite bend my mind around to it
> :)

The problem you're facing is that you have to think of the arrow
operator (->) as a type constructor.  IOW, to unify :

    a b c     with    t -> [Char]

you have the following "assignments":

    a ~ (->)
    b ~ t
    c ~ [Char]

In another other words,

    t -> [Char]    is the same as    (->) t [Char]

Now it's easy to see whats happening.  Note that (->) is an
instance to Arrow, in GHCi:

    Prelude Control.Arrow> :i Arrow
    class (Control.Category.Category a) => Arrow a where
      arr    :: (b -> c) -> a b c
      first  :: a b c -> a (b, d) (c, d)
      second :: a b c -> a (d, b) (d, c)
      (***)  :: a b c -> a b' c' -> a (b, b') (c, c')
      (&&&)  :: a b c -> a b c' -> a b (c, c')
      	-- Defined in Control.Arrow
    instance Arrow (->) -- Defined in Control.Arrow   <<< HERE <<<
    instance (Monad m) => Arrow (Kleisli m) -- Defined in Control.Arrow

Specializing those types to Arrow (->) and using the common infix
notation we have that:

      arr    :: (b -> c) -> (b -> c)
      first  :: (b -> c) -> ((b, d) -> (c, d))
      second :: (b -> c) -> ((d, b) -> (d, c))
      (***)  :: (b -> c) -> (b' -> c') -> ((b, b') -> (c, c'))
      (&&&)  :: (b -> c) -> (b' -> c') -> (b -> (c, c'))

Note that 'arr = id'. That's why we may use all Arrow functions
on, err, plain functions without having wrap everything with
'arr' (as you would with any other arrow).

It's a good exercise to try to reproduce the definition of the
Arrow (->) instance by defining the functions above.  Most
definitions, if not all, are just the corresponding free theorems
(meaning roughly that the definition follows from the type
because that's the only definition that doesn't have
undefined's).

HTH!

--
Felipe.


More information about the Beginners mailing list