我想编写一个给出选项引用列表的函数,并检查每个引用是否为None
。也就是说,我想要一个功能
let check rs =
List.for_all (fun r -> (!r) != None) rs
let _ =
check [ref (Some 5); ref (Some true)]
这不起作用。编译器找不到列表[ref (Some 5); ref (Some true)]
的类型,即使check
函数看起来本质上没问题,但它具有很好的多态'a option ref list -> bool
类型。
有没有办法让这项工作?
我从上面提炼出玩具示例的真实情况是,我正在将一些命令行参数解析为一堆引用。一些参数是字符串,一些是int,等等。最初所有引用都设置为None
,当解析器找到命令行参数时,它会设置对Some ...
的相应引用。完成解析之后,我发现自己想要遍历引用的子集以确保它们不是None
,因为我希望相应的命令行参数是必需的。
答案 0 :(得分:3)
OCaml不支持异构容器。您可以尝试解决这个问题:
type arg =
| Unset
| Int of int
| Bool of bool
(* etc *)
let check rs =
List.for_all (fun r -> (!r) <> Unset) rs
let _ =
check [ref (Int 5); ref (Bool true); ref Unset]
答案 1 :(得分:1)
查看问题的一种方法是,您的参数列表无法在OCaml中获得类型:
# [ ref (Some 5); ref (Some true) ];;
Error: This expression has type bool option ref
but an expression was expected of type int option ref
Type bool is not compatible with type int
如果您愿意将引用包装在对象界面中,则可以使用以下列表:
# class cr x = object method is_set = !x <> None end;;
class cr : 'a option ref -> object method is_set : bool end
# let reflist = [ new cr (ref (Some 5)); new cr (ref (Some true))];;
val reflist : cr list = [<obj>; <obj>]
然后你可以检查列表中的所有元素:
# List.for_all (fun x -> x#is_set) reflist;;
- : bool = true