zip

let zip l1 l2 =

    let rec zip' a b r = 
        match (a, b) with
        | ([], []) -> r
        | ( (ah::at), (bh::bt) ) -> zip' at bt ( (ah,bh) :: r)
        | _ -> []
    in

    zip' l1 l2 [] |> List.rev
;;
utop # assert ( (zip [1;2;3] ["a";"b";"c"]) = [(1, "a"); (2, "b"); (3, "c")] );;
- : unit = ()

unzip

let unzip zipped_list =

    let rec unzip' r1 r2 = function
    | [] -> (r1, r2)
    | (v1, v2)::t -> unzip' (v1::r1) (v2::r2) t
    in

    unzip' [] [] zipped_list |> function (a, b) -> ((List.rev a), (List.rev b))
;;
utop # assert ( (unzip [(1, "a"); (2, "b"); (3, "c")]) = ([1;2;3], ["a";"b";"c"]) );;
- : unit