Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can foldr take a function with three arguments?

I was having a look at some list operations and came across !!:

(!!)                    :: [a] -> Int -> a
xs !! n
  | n < 0     = negIndex
  | otherwise = foldr (\x r k -> case k of
                                   0 -> x
                                   _ -> r (k-1)) tooLarge xs n

The function (\x r k -> ...) has type a -> (Int -> a) -> Int -> a, but foldr takes a function that should only accept two arguments:

foldr            :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
          where
            go []     = z
            go (y:ys) = y `k` go ys

Can someone explain to me why foldr accepts a function that takes 3 arguments with the following type a -> (Int -> a) -> Int -> a? Especially since the result should have the same type as the second argument?

like image 289
srghma Avatar asked Oct 18 '22 09:10

srghma


1 Answers

-> is right-associative. So a -> b -> c is a -> (b -> c). Therefore, your type

a -> (Int -> a) ->  Int -> a

is the same as

a -> (Int -> a) -> (Int -> a)

and we can see that it fits foldr's type quite well.

like image 53
Zeta Avatar answered Oct 21 '22 02:10

Zeta