Home > Software design >  Adding two list in OCaml
Adding two list in OCaml

Time:09-28

let rec add_lists (xs : float list) (ys : float list): float list option =
  match xs ys with
  | ([],[]) -> Some[]
  | (x::xs', []) -> None
  | ([],y::ys') -> None 
  | hd::tl ->
      (match xs ys with 
       |[] -> None
       |hd2 :: tl2 ->(hd hd2):: (add_lists tl tl2) 
      )

I wanted to add 2 list together. To add the elements of two lists together, if they are different lengths return None.

Examples: add_lists [1.; 2.] [3.; 4.] = Some([4.; 6.]) add_lists [] [1.2] = None

CodePudding user response:

I see two problems. In your outer match you have:

match xs ys with
    . . .

In OCaml the expression xs ys is a call to a function named xs with ys as the parameter. This doesn't make sense since xs is not a function.

Most of your match cases have the form (pat1, pat2), i.e., a pair consisting of two patterns. This makes a lot of sense. But you need to match a pair against them. So perhaps your outer match should say this:

match (xs, ys) with
. . .

The second problem I see is that the last pattern of your outer match is not a pair. If you make it into a pair you should find that you don't need the second (inner) match.

CodePudding user response:

Immediately you have a typo.

match xs ys with

Should be:

match xs, ys with

You also have a type error when you match hd::tl instead of a tuple of lists.

If both lists are not empty, you need to recursively call your function on the tails of the two lists, and use pattern matching to figure out if that returned None or Some lst.

let rec add_lists xs ys =
  match xs, ys with
  | [], [] -> Some []
  | x::xs', [] -> None
  | [], y::ys' -> None 
  | x::xs', y::ys' ->
    (match add_lists xs' ys' with
     | None -> (* ... *)
     | Some lst -> Some (* ... *) )

Now, of course we could rearrange this to eliminate one pattern.

let rec add_lists xs ys =
  match xs, ys with
  | [], [] -> Some []
  | x::xs', y::ys' ->
    (match add_lists xs' ys' with
     | None -> (* ... *)
     | Some lst -> Some (* ... *) )
  | _ -> None

Of course, this is all a very long-winded way to write:

let add_lists lst1 lst2 =
  match List.map2 ( .) lst1 lst2 with 
  | lst -> Some lst 
  | exception _ -> None

CodePudding user response:

let add_lists (xs : float list) (ys : float list): float list option =
  let rec aux acc first second =
    match first, second with
    | [], [] -> Some(acc)
    | [], hd::tl -> None
    | hd::tl, [] -> None
    | hd::tl, hd'::tl' -> aux ((hd  . hd')::acc) (List.tl first) (List.tl second)
  in
  let res = aux [] xs ys in
  match res with
  | Some(x) -> print_string "Returned"; Some(List.rev x)
  | None -> print_string "Lists not same length"; None

Works with the good output.

Edit: Tail Recursive so you get good grades :)

  • Related