OCaml:查找特定类型的值

发布于 2024-12-06 04:54:08 字数 706 浏览 3 评论 0原文

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

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

I have the list of some values where I need to find out which kind of value is first:

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

Is there a way to do so without touching all types of MyType within find_first - is it possible to compare types of two values?
Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如日中天 2024-12-13 04:54:08

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

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

  2. 但是模式并不是一等公民。您不能从列表构建模式(顺便说一句,[MGamma, MAlpha, Mbeta] 是您的问题中无法编译的内容之一),也不能将模式作为参数传递到一个函数。

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

The code you have posted would not compile, but I think you are looking for the following information:

  1. It is possible to write so-called or-patterns, as in, for instance, (function MAlpha | MBeta _ -> ...).

  2. But patterns are not first-class citizens. You cannot build a pattern from a list (and by the way, [MGamma, MAlpha, MBeta] is one of the things that does not compile in your question), nor can you pass a pattern as argument to a function.

  3. However, you can build and pass around a function that matches for a pattern, so if you are willing to change your function find_first to take a function instead of a list for what, it will be more convenient to use.

小姐丶请自重 2024-12-13 04:54:08

另一种看待这个问题的方法是,你的类型有一个等价关系;即,您在某些地方希望将所有 MAlpha 视为相同,所有 Mbeta 相同,以及所有 MGamma是一样的。等价关系的标准处理是选择一个代表整组等价值(等价类)的代表性元素。

在您的情况下,您可以使用 MAlpha 表示所有 MAlpha (但只有其中一个),使用 Mbeta [] 表示所有MBeMGamma ("", 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 *)

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

您可能想查找列表中的特定值,而不是规范化值。我认为该案例的变化应该非常明显。

这也回答了你问题的第二部分。一旦找到要查找的内容,List.find 函数就会停止。

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

如果列表中没有与您所说的内容类似的元素,则此版本的 find_first 将引发异常 Not_found。这是另外一个需要考虑的事情。

Another way to look at this is that you have an equivalence relation for your type; i.e., you have some places where you want to treat all the MAlphas the same, all the MBetas the same, and all the MGammas the same. A standard handling for equivalence relations is to pick a representative element that represents the whole set of equivalent values (the equivalence class).

In your case you could use MAlpha to represent all the MAlphas (but there's only one of them), MBeta [] to represent all the MBetas and MGamma ("", 0) to represent all the MGammas. You would have a function to calculate the representative value from a given one:

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

I have written code like this and it doesn't come out too bad. In your case it allows you to specify the what parameter a little bit naturally. One downside, though, is that you can't pattern match against malpha, mbeta, and mgamma. You have to do equality comparisons against them.

It may be that you wanted to find the specific value in the list, rather than the canonicalized value. I think the changes for that case should be pretty clear.

This also answers the second part of your question. The List.find function will stop as soon as it finds what it's looking for.

OCaml defines an ordering relation for all types that don't contain functional values in them. If this built-in (polymorphic) ordering doesn't do what you want, you have to define your own. You would certainly need to do this to compare values of two different types; but that is not what you're doing here.

If there's no element in the list that looks like what you said you wanted, this version of find_first will raise the exception Not_found. That's something else to think about.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文