如何检查F#中的引用相等性?

如何检查F#中的引用相等性?,f#,equality,F#,Equality,F#对=运算符使用结构相等,这几乎总是您想要的: let a = [1; 2; 3] let b = [1; 2; 3] printfn "%A" (a = b) // Prints "true" 但在一些算法中,能够问“这两个东西是同一个对象吗?”这可能很重要,例如,这有助于检测图形中的循环。那么我如何要求F#中的引用相等呢?也就是说,如何编写下面的isSameObject函数 let isSameObject x y = ??? let a = [1; 2; 3] let b = [1;

F#对
=
运算符使用结构相等,这几乎总是您想要的:

let a = [1; 2; 3]
let b = [1; 2; 3]
printfn "%A" (a = b)  // Prints "true"
但在一些算法中,能够问“这两个东西是同一个对象吗?”这可能很重要,例如,这有助于检测图形中的循环。那么我如何要求F#中的引用相等呢?也就是说,如何编写下面的
isSameObject
函数

let isSameObject x y = ???
let a = [1; 2; 3]
let b = [1; 2; 3]
let a' = a
printfn "%A" (isSameObject a b)  // Prints "false"
printfn "%A" (isSameObject a a')  // Prints "true"

事实证明,答案是使用:

关于堆栈溢出,我可以找到一个问题: 由于这个问题的主题几乎让我一眼就看穿了它,我想我会再次问(并回答)这个问题。希望这个问题的主题行能让你在谷歌搜索“F#中的引用平等”这样的术语时更容易找到

那么
obj.ReferenceEquals
呢?

在评论中,Fyodor Soikin询问
obj.ReferenceEquals
有什么问题。答案是“不多”,但对于大多数F代码来说,
语言原语有两种方式。PhysicalQuality
优于
obj.ReferenceEquals

1)
PhysicalEquality
在传递两种不同的类型时抛出编译器错误,而
obj.ReferenceEquals
只接受两个
obj
s,因此愉快地尝试将
int list
char list
进行比较:

let a = [1;2;3]
let b = ['a';'b';'c']

obj.ReferenceEquals(a,b) // Returns false
LanguagePrimitives.PhysicalEquality a b // Compiler error
2)
PhysicalQuality
不允许您比较值类型,只允许比较引用类型
obj.ReferenceEquals
将允许您比较两种值类型,并将首先隐式地将它们装箱。但它会分别对每个对象进行装箱,这意味着即使给它“相同”的值对象,它也会始终返回false:

let n = 3
let n' = n
obj.ReferenceEquals(n,n') // Returns false!
LanguagePrimitives.PhysicalEquality n n' // Compiler error
当然,还有另一个区别,可以归结为个人偏好和易用性
PhysicalEquality
采用curried样式参数,这与类型推断和部分应用程序配合得很好
obj.ReferenceEquals
采用元组样式参数,这意味着使用起来有点难看


出于所有这些原因,
LanguagePrimitives.PhysicalEquality
在几乎所有场景中都比
obj.ReferenceEquals

@FyodorSoikin更好地使用它-我写了两条评论来回答你的问题,然后意识到它们在答案中会更好,并给出了代码示例。这样就可以了:
obj.ReferenceEquals
不错,但是
PhysicalEquality
更好,因为如果您尝试比较两种不同的类型,它会给您带来类型错误。(这几乎肯定是代码中的一个bug,您希望编译器帮助您捕获它)。
let n = 3
let n' = n
obj.ReferenceEquals(n,n') // Returns false!
LanguagePrimitives.PhysicalEquality n n' // Compiler error