val exists2 : ('a -> 'b -> bool) -> 'a list -> 'b list -> bool
However if i want to exhibit one adequate pair what i need is :
val exists2_opt : ('a -> 'b -> bool) -> 'a list -> 'b list -> ('a,'b) option
Moreover what i want is actually to catch all adequate pairs so what i need is :
val filter2 : ('a -> 'b -> bool) -> 'a list -> 'b list -> ('a,'b) list
let rev_append_map_filter p f la lb =
let rec loop l acc =
match l with
| [] -> acc
| h::t ->
if p h then loop t (f h::acc)
else loop t acc
in loop la lb
let rec filter2 p la lb =
match la with
| [] -> []
| a::l -> rev_append_map_filter (p a) (fun b -> a,b) lb (filter2 p l lb)
An easy way to do this [something else] is to zip the lists first:
> let find_map2 f xs ys = List.find_map f (List.combine xs ys);;
val find_map2 : ('a * 'b -> 'c option) -> 'a list -> 'b list -> 'c option
> let filter2 f xs ys = List.filter_map f (List.combine xs ys);;
val filter2 : ('a * 'b -> 'c option) -> 'a list -> 'b list -> 'c list
The temporary list can be avoided with Seq:
> let find_map2 f xs ys = Seq.find_map f (Seq.zip (List.to_seq xs) (List.to_seq ys));;
val find_map2 : ('a * 'b -> 'c option) -> 'a list -> 'b list -> 'c option
> let filter2 f xs ys = List.of_seq (Seq.filter_map f (Seq.zip (List.to_seq xs) (List.to_seq ys)));;
val filter2 : ('a * 'b -> 'c option) -> 'a list -> 'b list -> 'c list
It looks like you’re trying to find all the pairs (x,y) that satisfy p x y where x and y can occur anywhere in the lists, not just in corresponding positions. In other words, you want
filter2 (fun x y -> x < 2 && y > 20) [0; 1; 2; 3] [10; 20; 30; 40]
to return
[(0, 30); (0, 40); (1, 30); (1, 40)]
If so, then you could write your filter2 like this:
open ListLabels
let when_list c v = if c then [v] else []
let filter2 p l r =
concat_map l ~f:(fun x ->
concat_map r ~f:(fun y ->
when_list (p x y) (x, y)))
and you could write exists2_opt similarly, like this:
let when_opt c v = if c then Some v else None
let exists2_opt p l r =
find_map l ~f:(fun x ->
find_map r ~f:(fun y ->
when_opt (p x y) (x, y)))
let ( let++ ) o f = List.find_map f o
let exists2_opt p l r =
let++ x = l in
let++ y = r in
when_opt (p x y) (x, y)
let ( let** ) o f = List.concat_map f o
let filter2 p l r =
let** x = l in
let** y = r in
when_list (p x y) (x, y)
It looks like you’re trying to find all the pairs (x,y) that satisfy p x y where x and y can occur anywhere in the lists, not just in corresponding positions.
You are right, i fooled myself, exists2_opt & filter2 are ill-named, it’s nothing positionnal like List.exists2. Same type but not same meanning ! exists_two & filter_two could be better names.