2

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

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的情况下这样做- 是否可以比较两个值的类型?谢谢你。

4

2 回答 2

4

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

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

  2. 但是模式不是一等公民。您不能从列表中构建模式(顺便说一下,[MGamma, MAlpha, MBeta]这是在您的问题中无法编译的事情之一),也不能将模式作为参数传递给函数。

  3. 但是,您可以构建和传递与模式匹配的函数,因此如果您愿意将函数更改find_first为采用函数而不是列表what,则使用起来会更方便。

于 2011-09-24T12:05:57.297 回答
3

另一种看待这一点的方法是,您的类型具有等价关系;即,你有一些地方你想把所有的MAlphas都一样,所有的MBetas都一样,所有的MGammas都一样。等价关系的标准处理是选择代表整个等价值集(等价类)的代表性元素。

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

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 *)

我已经编写了这样的代码,结果还不错。在您的情况下,它允许您what自然地指定参数。但是,一个缺点是您不能对malpha,mbeta和进行模式匹配mgamma。您必须对它们进行平等比较。

您可能想在列表中查找特定值,而不是规范化值。我认为这种情况的变化应该很清楚。

这也回答了您问题的第二部分。该List.find功能将在找到所需内容后立即停止。

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

如果列表中没有元素看起来像您所说的那样,则此版本的find_first将引发异常Not_found。这是要考虑的其他事情。

于 2011-09-24T15:27:08.153 回答