键值联合函数ocaml



我试图使一个函数,需要与(key,value)对的两个列表,比较关键,如果它是相同的,它返回的联合列表:[(1,["one"]);(1,["uno"])][(2,["two"]);(1,["eden"])]应该返回[(1,["one";"uno";"eden"]);(2,"two")]这段代码返回单位,我不确定为什么:

type 'a kvs=(int*('a list))list ;;
let rec union l1 l2 =  match l1 with 
|[]->l2
|h::t-> let (k1,v1) = h and (k2,v2)=(List.hd l2) in 
if (k1=k2)then begin 
v1@v2;     (*this part*)
union t l2
end 
else union t l2;;
let l1 = [(1,["three"]);(1,["tri"])];;
let l2 = [(2,["three"]);(1,["tri"])];;
union l1 l2;;    


对@glennsl的评论进行一点扩展:当您使用stmt1; stmt2时,stmt1的结果将被丢弃。如果您使用stmt1的副作用,那么该构造仍然是有用的。例如函数

let f x =
Printf.printf "you passed the string %s" x;
x

不改变其结果,但打印字符串x作为附加的副作用。您看到的警告总是在stmt1没有类型单元时发出,因为您隐式地忽略了它的值。相反,最好使用模式

let v = v1@v2 in
union t l2

使您可以在递归调用中使用v

如果你只是想让警告消失,你总是可以使用ignore(stmt1); stmt2来无声地丢弃stmt1的值,但在大多数情况下,这不是你想要的。

假设您想要一个可以获得所需输出的函数,并且输出中的顺序无关紧要,以下是我认为您需要的…

let union l1 l2 =
let
filter_unique = List.fold_left (fun acc curr -> if not (List.exists (fun y -> y = curr) acc) then (curr::acc) else acc) []
in
let rec unique_unions acc = function
| [] -> acc
| ((key, value)::tail) ->
try
let existing_values = List.assoc key acc in
unique_unions ((key, filter_unique (existing_values @ value)) :: (List.remove_assoc key acc)) tail
with
Not_found -> unique_unions ((key, value) :: acc) tail
in    
unique_unions [] (l1 @ l2)

最新更新