Home > other >  This expression has type 'a list option but an expression was expected of type 'b list
This expression has type 'a list option but an expression was expected of type 'b list

Time:03-16

I am writing a function in ocaml that returns the longest list in a list using the type option and using List.fold_right

let longest( lst : 'a list list) : 'a list option = 
  List.fold_right( fun (i : 'a list)  (y : 'a list option) -> if List.length i > List.length y then (Some i) y else y) lst None 

However i keep getting this error

This expression has type 'a list option
but an expression was expected of type 'b list

The function should return Some followed by the longest list or none if it is empty

CodePudding user response:

Let's make this a bit easier to digest.

let longest (lst : 'a list list) (x : 'a list option) = 
  List.fold_right 
    (fun (i : 'a list)  (y : 'a list option) -> 
       if List.length i > List.length y then (Some i) y 
       else y) 
    lst 
    None 

The specific issue this is complaining about is related to:

List.length y

In this situation y is supposed to be of type 'a list option but List.length expects a value of type 'a list.

You need to do some pattern-matching in the function you pass to List.fold_right to determine if the init value (in your code confusingly represented as y) is None or Some ... and then handle it accordingly.

It might look something like the following. Please note that the type annotations you've used are extraneous as OCaml will infer the types.

let longest lst =
  List.(
    let f x i =
      match i with 
      | None                                  -> ...
      | Some lst' when length x > length lst' -> ...
      | _                                     -> ...
    in
    fold_right f lst None
  )

CodePudding user response:

Handling [] as special case, dropping the unused x argument and reducing the number of times List.length is called to once per list I get this:

let longest lst =
  match lst with   
   | [] -> None   
   | x :: xs -> 
      Some (fst (List.fold_right
        (fun i ((y, ly) as p) ->
          let li = List.length i
          in
            if li > ly
            then (i, li)
            else p)
        xs
        (x, List.length x)));;

val longest : 'a list list -> 'a list option = <fun>
# longest [];;
- : 'a list option = None
# longest [[1]; [1;2;3]; [1;2]];;
- : int list option = Some [1; 2; 3]
  • Related