(* Strategy: (1) break down the input based on its type in to a set of cases * there can be more than one way to do this (2) make the assumption (the induction hypothesis) that your recursive function works correctly when called on a smaller list * you might have to make 0,1,2 or more recursive calls (3) build the output (guided by its type) from the results of recursive calls *) (* Given a list of pairs of integers, produce the list of products of the pairs prods [(2,3); (4,7); (5,2)] == [6; 28; 10] *) let rec prods (xs: (int * int) list) : int list = match xs with [] -> [] | (p1,p2)::tail -> (p1*p2)::prods tail ;; (* Given two lists of integers, return None if the lists are different lengths otherwise stitch the lists together to create Some of a list of pairs zip [2; 3] [4; 5] == Some [(2,4); (3,5)] zip [5; 3] [4] == None zip [4; 5; 6] [8; 9; 10; 11; 12] == None *) let rec zip (xs:int list) (ys:int list) : (int*int) list option = match (xs, ys) with ([], []) -> Some [] | (hd::tail, []) -> None | ([],hd::tail) -> None | (x::xtail, y::ytail) -> (match zip xtail ytail with Some zs -> Some ((x,y)::zs) | None -> None) ;;