-1

I asked this question a few days ago but now I have more understanding on the subject. But I still get problem that operator and operand dont agree:

Using ListPair.foldr I need to create a function zipWith that combines pairwise two lists. The type of the overall function should be:

zipWith : ('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list

ListPair.foldr : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c

- zipWith (fn (x, y) => x + y) [1,2,3,4] [10,20,30,40];
  val it = [11,22,33,44] : int list

My attempt:

fun zipWith xs ys = ListPair.foldr(zipWith(x,y,z) => (x+y)::z) 0 xs ys
user2012107
  • 9
  • 1
  • 3

1 Answers1

4

There are several things wrong in your attempt:

  1. The parameters. You have zipWith xs ys, but the type says that the first parameter has to be a function, so change that to zipWith f xs ys.
  2. You're calling zipWith recursively. ListPair.foldr takes care of that for you, though, so don't.
  3. You're giving ListPair.foldr 0 as its starting value. Fold-functions always take a starting value of the same type as the return value - we want zipWith to return a list, so the fold-function should take a list as its starting value. The empty list, that is.

Think about how ListPair.foldr works. We can do it one parameter at a time. The type of ListPair.foldr is:

fn : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c

The first parameter is a function with the type:

fn : 'a * 'b * 'c -> 'c

Let's make a toy function as an example:

fun foo (a, b, acc) = a+b :: acc

This function takes two numbers and a list, adds the two numbers together, puts them in front of the list, and returns it. The type is:

fn : int * int * int list -> int list

Which corresponds nicely with our type signature from the first parameter of ListPair.foldr.

Now, let's look at the type of ListPair.foldr foo.

fn : int list -> int list * int list -> int list

The next parameter is an int list - the starting value for the folding. Great, we already figured out that this is the empty list. The type of ListPair.foldr foo [] is:

fn : int list * int list -> int list

The last parameter is a tuple containing two lists. We put in some random lists, and try it out in an sml interpreter:

- ListPair.foldr foo [] ([1,2,3],[10,20,30])
> val it = [11, 22, 33] : int list

Now, all you need to do is to replace the parameters to ListPair.foldr (foo and the two random lists) with parameters from zipWith, and you're done.

Tayacan
  • 1,896
  • 11
  • 15