Working backwards to a solution ------------------------------- A general technique and several sample solutions for the tabulation problem (from Lab 2). Start with a statement of what the function should do, given certain arguments of known value: > tabulate (*) [1..3] [1..4] [[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12]] Now work through backwards to an answer; at each step we abstract away some more of the structure, until we see occurrences of the sample arguments "as-is" in the code (these become parameters): [ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12] ] == [ [1*1, 1*2, 1*3, 1*4], [2*1, 2*2, 2*3, 2*4], [3*1, 3*2, 3*3, 3*4] ] == [ map (1*) [1, 2, 3, 4], map (2*) [1, 2, 3, 4], map (3*) [1, 2, 3, 4] ] == map (uncurry map) [ ( (1*), [1, 2, 3, 4]), ( (2*), [1, 2, 3, 4]), ( (3*), [1, 2, 3, 4]) ] == map (uncurry map) (zip [ (1*), (2*), (3*) ] (repeat [1, 2, 3, 4])) == map (uncurry map) (zip [ (*1), (*2), (*3) ] (repeat [1, 2, 3, 4])) == map (uncurry map) (zip (map (*) [1,2,3]) (repeat [1, 2, 3, 4])) == map (uncurry map) (zip (map f xs) (repeat ys)) where f = (*) xs = [1,2,3] ys = [1,2,3,4] SO, tabulate f xs ys = map (uncurry map) (zip (map f xs) (repeat ys)) Or, we can work through backwards to a *different* answer (here using zipWith): [ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12] ] == [ [1*1, 1*2, 1*3, 1*4], [2*1, 2*2, 2*3, 2*4], [3*1, 3*2, 3*3, 3*4] ] == [ map (1*) [1, 2, 3, 4], map (2*) [1, 2, 3, 4], map (3*) [1, 2, 3, 4] ] == zipWith map [(1*), (2*), (3*)] (repeat [1,2,3,4]) == zipWith map [(*1), (*2), (*3)] (repeat [1,2,3,4]) == zipWith map (map (*) [1,2,3]) (repeat [1,2,3,4]) == zipWith map (map f xs) (repeat ys) where f = (*) xs = [1,2,3] ys = [1,2,3,4] SO, tabulate f xs ys = zipWith map (map f xs) (repeat ys) Here is yet a *still* different answer, using only flip, map and function composition: [ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12] ] == [ [1*1, 1*2, 1*3, 1*4], [2*1, 2*2, 2*3, 2*4], [3*1, 3*2, 3*3, 3*4] ] == [ map (1*) [1, 2, 3, 4], map (2*) [1, 2, 3, 4], map (3*) [1, 2, 3, 4] ] == [ flip map [1, 2, 3, 4] (1*), flip map [1, 2, 3, 4] (2*), flip map [1, 2, 3, 4] (3*) ] == map (flip map [1,2,3,4]) [ (1*), (2*), (3*) ] == map (flip map [1,2,3,4]) [ (*1), (*2), (*3) ] == map (flip map [1,2,3,4]) (map (*) [1,2,3]) == map (flip map ys) (map f xs) where f = (*) xs = [1,2,3] ys = [1,2,3,4] == map (flip map ys . f) xs where f = (*) xs = [1,2,3] ys = [1,2,3,4] SO, tabulate f xs ys = map (flip map ys . f) xs Finally, here is an answer using nested list comprehensions ("straight" list comprehension is especially simple, but it merges the two-level lists of the result together): [ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12] ] == [ [1*1, 1*2, 1*3, 1*4], [2*1, 2*2, 2*3, 2*4], [3*1, 3*2, 3*3, 3*4] ] == [ [x*y | y <-[1,2,3,4]] | x<-[1,2,3] ] == [ [x `f` y | y <-ys] | x<-xs ] where f = (*) xs = [1,2,3] ys = [1,2,3,4] SO, tabulate f xs ys = [ [x `f` y | y <-ys] | x<-xs ]