OCaml:找到特定类型的值

时间:2011-09-24 11:42:25

标签: ocaml static-typing

我有一些值的列表,我需要找出哪种值是第一个:

type my_types =
    | MAlpha
    | MBeta of int list
    | MGamma of string * int

let find_first where what =
    List.iter ( fun m ->
        | MAlpha ->
            (* iterate frough "what" to find if it was asked to look and return it if it was *)
        | (* do the same for all other types *)
    ) where;
;;

let main =
    let where_to_find = [MGamma, MAlpha, MBeta] in
    let what_to_find = [MAlpha, MBeta] in
    (match (first_found where_to_find what_to_find) with
    | MAlpha ->
        (* should return this *)
    )
;;

有没有办法在不触及 find_first 中所有类型的 MyType 的情况下执行此操作 - 是否可以比较两个值的类型? 谢谢。

2 个答案:

答案 0 :(得分:4)

您发布的代码无法编译,但我认为您正在寻找以下信息:

  1. 可以编写所谓的or-patterns,例如(function MAlpha | MBeta _ -> ...)

  2. 但模式不是一等公民。你不能从列表中构建一个模式(顺便说一下,[MGamma, MAlpha, MBeta]是你的问题中没有编译的东西之一),你也不能将模式作为参数传递给函数。

    < / LI>
  3. 但是,您可以构建并传递与模式匹配的函数,因此如果您愿意更改函数find_first以获取函数而不是what的列表,使用起来会更方便。

答案 1 :(得分:3)

另一种看待这种情况的方法是你的类型具有等价关系;也就是说,您有一些地方要将所有MAlpha视为相同,所有MBeta都相同,且所有MGamma都相同。等价关系的标准处理是选择代表整组等价值(等价类)的代表性元素。

在您的情况下,您可以使用MAlpha代表所有MAlpha(但只有其中一个),MBeta []代表所有MBeta和{ {1}}代表所有MGamma ("", 0)个。您将有一个函数来计算给定值的代表值:

MGamma

我已经编写了这样的代码,并没有太糟糕。在您的情况下,它允许您自然地指定let malpha = MAlpha let mbeta = MBeta [] let mgamma = MGamma ("", 0) let canonicalize = function | MAlpha -> malpha | MBeta _ -> mbeta | MGamma _ -> mgamma let find_first where what = canonicalize (List.find (fun x -> List.mem (canonicalize x) what) where) let main () = let where_to_find = [MGamma ("a", 3); MAlpha; MBeta [3; 4]] in let what_to_find = [malpha; mbeta] in try let found = find_first where_to_find what_to_find in if found = malpha then (* what to do *) else if found = mbeta then (* what to do *) else (* what to do *) with Not_found -> (* nothing was there *) 参数。但有一个缺点是,您无法与whatmalphambeta进行模式匹配。你必须对它们进行平等比较。

您可能希望在列表中找到特定值,而不是规范化值。我认为这种情况的变化应该非常明确。

这也回答了你问题的第二部分。 mgamma函数会在找到所需内容后立即停止。

OCaml为所有不包含功能值的类型定义了一个排序关系。如果这种内置(多态)排序不能满足你的需求,你必须定义自己的。你肯定需要这样做来比较两种不同类型的值;但那不是你在这里做的。

如果列表中没有符合您所说内容的元素,则此版本的List.find将引发异常find_first。这是另一个需要考虑的事情。