Search code examples
functionhaskelltypesargumentsfold

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?


Solution

  • -> 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.