2
votes

I just began to learn haskell recently. I have some confusion of declare function type in the function definition. For example if we want to define a foldr function:

foldr :: (a->b->b)->b->[a]->b
foldr f v [] = v
foldr f v (x:xs) = f x (foldr f v xs)

Thus, foldr (+) 0 [1,2,3,4] = sum [1,2,3,4] = 10.

My question is: can I just change it to something like :

foldr :: (a->a->a)->a->[a]->a
 OR:
foldr :: (a->b->c)->x->[y]->z

I didn't find a place to explain the choice/requirements of letters in the definition. Thanks!


Update: I tested it with:

 foldr :: (a->b->c)->x->[y]->z

Got the following err:

   Couldn't match type `y' with `a'
  `y' is a rigid type variable bound by
      the type signature for folderr :: (a -> b -> c) -> x -> [y] -> z
      at test.hs:3:1
  `a' is a rigid type variable bound by
      the type signature for folderr :: (a -> b -> c) -> x -> [y] -> z
      at test.hs:3:1

If changed everything to a, it works. I must have missing some points here.


As explained in @sepp2k's comments. I tested using the following simple example:

     folderr :: (a->b->b)->b->[a]->b
     folderr f v [] = v
     folderr f v (x:xs) = f x (folderr f v xs)


     myop :: Int -> Bool -> Bool
     myop x y | x > 0 = True && y
              | otherwise = False && y

folderr (myop) True [3,3,222] -> True folderr (myop) True [3,2,-1] -> False

So a,b just means the types are different or not.

1
If you replaced both of the as with y, it would work. But by calling one a and the other y, you're saying that they can be different. But then the definition of the function treats them as the same, so you get the error.sepp2k

1 Answers

3
votes

The specific names of your type variables do not matter, that is the types a -> b -> c, x -> y -> z and foo -> bar -> baz are all completely equivalent.

What does matter is whether you use the same type variable multiple times or you use different ones. That is a -> b is a different type than a -> a. Specifically a -> b is more general because out of the concrete types Int -> Int, String -> String, Int -> String and String -> Int, a -> a would only match the first two (with a = Int and a = String respectively) whereas a -> b would match all four.