简体   繁体   中英

pairing an int with a list of ints in OCaml

I am using OCaml to write a function that takes a list of ints and an int element and returns a list of pairs where the first element of every pair is the int element and the second element of the pair is a member from the list. For example, let say I have the number 1 and the list [10; 20; 30] as inputs. I like the function to return [(1, 10); (1, 20); (1, 30)]. I wrote the following function:

let rec f (lst : int list) (elm : int) : (int*int) list =  
  match lst with 
  | [] -> failwith "empty list" 
  | [x] -> [(x, elm)];;

I am getting the following error:

Characters 59-120:                                                              
Warning 8: this pattern-matching is not exhaustive.                             
Here is an example of a value that is not matched:                               
_::_::_ val f : int list -> int -> (int * int) list = <fun> 

What am I missing?

Your patterns match lists of length 0 ( [] ) and of length 1 ( [x] ). The compiler is telling you that there are other lengths that a list might have, so your pattern is probably wrong (which is true).

I might note that it's not an error to get an empty list as an argument. Thinking this way will make it much harder to answer the problem. If you get an empty list, the correct answer is an empty list of pairs.

Here is your code

let rec f (lst : int list) (elm : int) : (int*int) list =  
  match lst with 
  | [] -> failwith "empty list" 
  | [x] -> [(x, elm)]

In your match , you listed two cases: [] and [x] .

Your first case is [] , you mean empty , no problem.

Your second case is [x] , what did you want to mean? In OCaml, it means a list with only one element .

How about the cases where there are more than one element?

For any if else or match with , you should include all cases.

When you fix this problem, you will soon find you really missed something more there.


Here is the correct code:

let rec f e l  =  
  match l with 
  | [] -> []
  | x::[] -> [(e,x)]
  | x::tl -> (e,x)::(f e tl)

Note

  1. above code is not tail-recursive and you normally should consider about it, I will leave that to you.
  2. you don't need ;; if you write your code in file and compile the file
  3. You don't need to declare types in most cases and that is one of the best thing ocaml has.
let rec f e  =  function
  | []    -> []
  | x::tl -> (e,x)::f e tl

Or

let f e = List.map (fun x -> (e,x))

Test

# f 1 [];;
- : (int * 'a) list = []
# f 1 [10;20;30];;
- : (int * int) list = [(1, 10); (1, 20); (1, 30)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM