[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