与fsharp中的等运算符进行比较

时间:2015-12-11 17:49:03

标签: f# f#-interactive

如果我有下一个类型:

rotateControl: true

我做了:

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)

我应该获得 true ,但是通过脚本进行的F#交互式给我 false 相反,如果我定义为:

let ca = Color(1.,1.,1.)
let cb = Color(1.,1.,1.)
ca = cb

返回 true 我是否在尝试以这种方式比较定义类型的两个值时做错了什么? 我怎样才能获得 true

由于

3 个答案:

答案 0 :(得分:4)

Color的OP定义是。默认情况下,类具有引用相等,就像在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;}

答案 1 :(得分:3)

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

答案 2 :(得分:-2)

首先,您应该阅读本页:

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)添加重载以进行成员比较