与 fsharp 中的相等运算符比较
comparing with equal operator in fsharp
如果我有下一个类型:
type Color(r: float, g: float, b:float) =
member this.r = r
member this.g = g
member this.b = b
static member ( * ) (c1:Color, c2:Color) =
Color (c1.r*c2.r, c1.g*c2.g, c1.b*c2.b)
static member Zero = Color(0.0,0.0,0.0)
我也是:
let ca = Color(1.,1.,1.)
let cb = Color(1.,1.,1.)
ca = cb
我应该获得 true,但是通过脚本进行的 F# 交互给我 false
相反,如果我定义为:
let ca = Color(1.,1.,1.)
let cb = ca
ca = cb
是returns是
尝试以这种方式比较已定义类型的两个值时,我做错了什么吗?
我怎样才能得到 true 结果呢?
谢谢
首先,您应该阅读此页面:
http://blogs.msdn.com/b/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx
它很好地说明了平等在 F#
中是如何运作的。
关于您的具体问题,您正在查看引用相等性和结构相等性之间的区别。可以添加如下注解
[<CustomEquality; CustomComparison>]
并且您可以向 Equals 方法添加重载 override x.Equals(other)
以进行成员比较
F# 实现了记录和联合的自动成员比较,但不支持 类。如果你想拥有它并使用 Color(r, g, b)
语法构造值,你可以使用单大小写联合。您将获得模式匹配作为奖励(参见我对 (*)
的实现)。
type Color =
| Color of r: float * g: float * b: float
member this.r = let (Color(r, _, _)) = this in r
member this.g = let (Color(_, g, _)) = this in g
member this.b = let (Color(_, _, b)) = this in b
static member (*) (Color(r1, g1, b1), Color(r2, g2, b2)) =
Color(r1 * r2, g1 * g2, b1 * b2)
static member Zero = Color(0., 0., 0.)
Color
的 OP 定义是 class。 类 默认情况下具有 引用相等性 ,就像在 C# 中一样。这意味着它们只有在字面上是相同的对象(指向相同的内存地址)时才相等。
只有 F# 中的功能数据类型具有 结构相等性。这些包括记录、可区分联合、列表和一些其他类型。
将 Color
定义为一条记录会更惯用:
type Color = { Red : float; Green : float; Blue : float }
此类型内置了结构相等性:
> let ca = { Red = 1.; Green = 1.; Blue = 1. };;
val ca : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
> let cb = { Red = 1.; Green = 1.; Blue = 1. };;
val cb : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
> ca = cb;;
val it : bool = true
如果你想为类型定义乘法和零,你也可以这样做:
let (*) x y = {
Red = x.Red * y.Red
Green = x.Green * y.Green
Blue = x.Blue * y.Blue }
let zero = { Red = 0.0; Green = 0.0; Blue = 0.0 }
这使您可以编写,例如:
> let product = ca * cb;;
val product : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
如果我有下一个类型:
type Color(r: float, g: float, b:float) =
member this.r = r
member this.g = g
member this.b = b
static member ( * ) (c1:Color, c2:Color) =
Color (c1.r*c2.r, c1.g*c2.g, c1.b*c2.b)
static member Zero = Color(0.0,0.0,0.0)
我也是:
let ca = Color(1.,1.,1.)
let cb = Color(1.,1.,1.)
ca = cb
我应该获得 true,但是通过脚本进行的 F# 交互给我 false 相反,如果我定义为:
let ca = Color(1.,1.,1.)
let cb = ca
ca = cb
是returns是 尝试以这种方式比较已定义类型的两个值时,我做错了什么吗? 我怎样才能得到 true 结果呢?
谢谢
首先,您应该阅读此页面:
http://blogs.msdn.com/b/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx
它很好地说明了平等在 F#
中是如何运作的。
关于您的具体问题,您正在查看引用相等性和结构相等性之间的区别。可以添加如下注解
[<CustomEquality; CustomComparison>]
并且您可以向 Equals 方法添加重载 override x.Equals(other)
以进行成员比较
F# 实现了记录和联合的自动成员比较,但不支持 类。如果你想拥有它并使用 Color(r, g, b)
语法构造值,你可以使用单大小写联合。您将获得模式匹配作为奖励(参见我对 (*)
的实现)。
type Color =
| Color of r: float * g: float * b: float
member this.r = let (Color(r, _, _)) = this in r
member this.g = let (Color(_, g, _)) = this in g
member this.b = let (Color(_, _, b)) = this in b
static member (*) (Color(r1, g1, b1), Color(r2, g2, b2)) =
Color(r1 * r2, g1 * g2, b1 * b2)
static member Zero = Color(0., 0., 0.)
Color
的 OP 定义是 class。 类 默认情况下具有 引用相等性 ,就像在 C# 中一样。这意味着它们只有在字面上是相同的对象(指向相同的内存地址)时才相等。
只有 F# 中的功能数据类型具有 结构相等性。这些包括记录、可区分联合、列表和一些其他类型。
将 Color
定义为一条记录会更惯用:
type Color = { Red : float; Green : float; Blue : float }
此类型内置了结构相等性:
> let ca = { Red = 1.; Green = 1.; Blue = 1. };;
val ca : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
> let cb = { Red = 1.; Green = 1.; Blue = 1. };;
val cb : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}
> ca = cb;;
val it : bool = true
如果你想为类型定义乘法和零,你也可以这样做:
let (*) x y = {
Red = x.Red * y.Red
Green = x.Green * y.Green
Blue = x.Blue * y.Blue }
let zero = { Red = 0.0; Green = 0.0; Blue = 0.0 }
这使您可以编写,例如:
> let product = ca * cb;;
val product : Color = {Red = 1.0;
Green = 1.0;
Blue = 1.0;}