OCaml:查找特定类型的值
我有一些值的列表,我需要找出哪种值是第一个:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您发布的代码无法编译,但我认为您正在寻找以下信息:
可以编写所谓的或模式,例如
(function MAlpha | Mbeta _ -> ...)
.但是模式并不是一等公民。您不能从列表构建模式(顺便说一句,
[MGamma, MAlpha, Mbeta]
是您的问题中无法编译的内容之一),也不能将模式作为参数传递到一个函数。但是,您可以构建并传递与模式匹配的函数,因此如果您愿意更改函数
find_first
以采用函数而不是what<的列表, /code>,使用起来会更方便。
The code you have posted would not compile, but I think you are looking for the following information:
It is possible to write so-called or-patterns, as in, for instance,
(function MAlpha | MBeta _ -> ...)
.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.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 forwhat
, it will be more convenient to use.另一种看待这个问题的方法是,你的类型有一个等价关系;即,您在某些地方希望将所有
MAlpha
视为相同,所有Mbeta
相同,以及所有MGamma
是一样的。等价关系的标准处理是选择一个代表整组等价值(等价类)的代表性元素。在您的情况下,您可以使用
MAlpha
表示所有MAlpha
(但只有其中一个),使用Mbeta []
表示所有MBe
和MGamma ("", 0)
来表示所有MGamma
。您将有一个函数来计算给定值的代表值:我已经编写了这样的代码,并且结果还不错。在您的情况下,它允许您自然地指定
what
参数。不过,它的一个缺点是您无法对malpha
、mbeta
和mgamma
进行模式匹配。你必须对它们进行平等比较。您可能想查找列表中的特定值,而不是规范化值。我认为该案例的变化应该非常明显。
这也回答了你问题的第二部分。一旦找到要查找的内容,
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
MAlpha
s the same, all theMBeta
s the same, and all theMGamma
s 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 theMAlpha
s (but there's only one of them),MBeta []
to represent all theMBeta
s andMGamma ("", 0)
to represent all theMGamma
s. You would have a function to calculate the representative value from a given one: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 againstmalpha
,mbeta
, andmgamma
. 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 exceptionNot_found
. That's something else to think about.