yesar
yesar

Reputation: 25

Why is this function curried?

To my understanding, curried functions should always return a function. However, in the code below, I believe this function returns a list. But when I check the type, it looks like a curried function.

fun zipWith f xs ys =
    case (xs,ys) of
         ([],_) => []
      | (_,[]) => []
      | (x::xs',y::ys') => (f(x,y)) :: zipWith f xs' ys'

The type:

val zipWith = fn : ('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list.

Could someone explain the type and how currying works in this function. Any help is appreciated!

Upvotes: 0

Views: 77

Answers (2)

molbdnilo
molbdnilo

Reputation: 66371

It is curried - you don't need to pass all the arguments at once, but it produces a list when all of them have "arrived".
It's common to write all the curried parameters on the left-hand side if the function is not meant to be primarily a "function-creating" function.

The definition looks more like the type if you write it on the (equivalent) form

fun zipWith f = fn xs =>
                  fn ys => 
                    case (xs,ys) of
                      ([],_) => []
                    | (_,[]) => []
                    | (x::xs',y::ys') => (f(x,y)) :: ((zipWith f) xs') ys'

Example of the "curriedness":

- val add = zipWith (op +);
val add = fn : int list -> int list -> int list
- val add_123 = add [1,2,3];
val add_123 = fn : int list -> int list
- add_123 [4,5,6];
val it = [5,7,9] : int list

Upvotes: 2

sepp2k
sepp2k

Reputation: 370112

fun f arg1 ... argN = exp is a syntactic shortcut for val rec f = fn arg1 => ... => fn argN => exp. So in your case we have:

val rec zipWith = fn f => fn xs => fn ys =>
    case (xs, ys) of
    ...

So zipWith is a function that, when given an argument f, returns another function that, when given an argument xs, ... and so on. In other words, it's curried.

Upvotes: 7

Related Questions