Option的行为大于(和等价)

Jar*_*rak 3 comparison f# optional

我正在为一个图像处理任务工作(这里并没有太大的相关性),我偶然发现F#的Option类型的行为让我感到惊讶,因为它执行了大于(>)的比较.在Stack Overflow,F#docs或更广泛的网络上,我找不到任何直接解释我应该期待的东西(下面有更多内容).

我正在看的具体部分看起来像:

let sort3Elems (arr: byte option []) = 
    if arr.[0] > arr.[1] then swap &arr.[0] &arr.[1]
    if arr.[1] > arr.[2] then swap &arr.[1] &arr.[2]
    if arr.[0] > arr.[1] then swap &arr.[0] &arr.[2]
Run Code Online (Sandbox Code Playgroud)

我将在四个字节选项的数组中传递(如果你想知道为什么这看起来很奇怪并且超级无功能,现在我故意试图重新实现一个算法的非函数式语言实现教科书).我期待这会导致编译器错误,它会抱怨无法直接比较选项.令我惊讶的是,这编译好了.好奇,我在F#Interactive中测试了它,其结果如下所示:

let arr: byte option [] = Array.zeroCreate 4;;
val arr : byte option [] = [|None; None; None; None|]

> arr.[0] <- Some(127uy);;
val it : unit = ()

> arr.[2] <- Some(55uy);;
val it : unit = ()

> arr.[0] > arr.[2];;
val it : bool = true

> arr.[0] < arr.[2];;
val it : bool = false

> arr.[0] < arr.[1];;
val it : bool = false

> arr.[0] > arr.[1];;
val it : bool = true

> arr.[2] > arr.[1];;
val it : bool = true

> arr.[3] > arr.[1];;
val it : bool = false

> arr.[3] < arr.[1];;
val it : bool = false

> arr.[3] > arr.[1];;
val it : bool = false
Run Code Online (Sandbox Code Playgroud)

在我看来,当询问Some是否大于(小于)None时,必须总是返回true(false),两个Nones总是返回false,并且两个相同包含类型的Somes比较包含的值(假设他们可以比较我想象的).这是有道理的,尽管我很惊讶.

想要证实这一点,我试图追踪一些可以解释我应该期待的行为的东西,但我找不到任何能够解决问题的方法.MS F#指南文档中的选项页面没有提及它,我在F#等地方找不到任何有趣和有利的东西.我甚至无法在MS API文档中的任何地方找到关于Option的页面... 在F#GitHub repo查看Option的来源并没有告诉我什么.我能找到的最好的是几年前Don Syme的博客文章,它实际上没有回答我的问题.有一些Stack Overflow问题讨论了与比较运算符或Option类型相关的主题,但我没有发现任何涉及两者组合的问题.

所以,我的问题是,对Option类型的执行是否大于/小于比较返回我上面推测的结果?我猜这是F#程序员中相当常见的知识,但这对我来说是新闻.作为一个子/相关问题,有谁知道我可以/应该在哪里寻找更多信息?谢谢.

Tom*_*cek 7

F#编译器自动为区分的联合和记录类型生成比较.由于选项只是一个有区别的联合,这也意味着您可以自动比较联合.我不确定是否有一个很好的网页记录这个,但你可以在F#规范的8.15.4节中找到一个描述:

8.15.4生成的CompareTo实现的行为

对于类型T,生成的System.IComparable.CompareTo实现的行为如下:

  • 将y参数转换为T类型.如果转换失败,请引发InvalidCastException.
  • 如果T是引用类型且y为null,则返回1.
  • 如果T是结构或记录类型,则按声明顺序在x和y的每个对应字段对上调用FSharp.Core.Operators.compare,并返回第一个非零结果.
  • 如果T是联合类型,则首先在两个值的并集案例的索引上调用FSharp.Core.Operators.compare,然后在union案例所携带的数据的每个对应的x和y字段对上调用.返回第一个非零结果.

如最后一个案例所述,选项案例首先比较案例.None索引小于,Some因此None值始终小于任何Some值.如果情况匹配,然后None = NoneSome nSome m比较基础nm.