[英]How to define operators for discriminated unions in f#
我有代码来实现基元之间的一些几何操作
type point = double * double
type shape =
| Point of point
| Line of point * point
| Vector of point
| Circle of point * double
with
member this.ToString = function
| Point (x,y) -> sprintf "(%f; %f)" x y
| Vector (x,y) -> sprintf "(%f; %f)" x y
| Line ((x0,y0),(x1,y1)) -> sprintf "(%f; %f)->(%f; %f)" x0 y0 x1 y1
| Circle ((x0,y0),radius) -> sprintf "(%f; %f)r%f" x0 y0 radius
let inline (-) (Point (x0,y0)) (Point (x1,y1)) = Vector (x0-x1,y0-y1)
let inline (+) (Point (x0,y0)) (Vector (x1,y1)) = Point (x0+x1,y0+y1)
并且编译器说操作符上的模式匹配并不详尽,尽管这只是一个警告。 如何在没有编译器抱怨的情况下,只在DU的特定子类型之间正确实现运算符?
运算符通常定义为静态成员:
type shape =
...
static member (-) (x, y) =
match x, y with
| Point (x0,y0), Point (x1,y1) -> Vector (x0-x1,y0-y1)
| Point (x0,y0), Vector (x1,y1) -> Point (x0+x1,y0+y1)
| _ -> failwith "invalid arguments"
关于你的尝试的一些注意事项:
作为一个侧面说明,你有另外一个问题,这是ToString
应符合在this
,但现在在一个匿名参数(相匹配,而不必型unit -> string
,它的shape -> string
。此外,它应该是用override
声明,而不是member
(这也会指出签名是错误的)。
基本问题是在编译时,编译器不知道您选择创建哪个特定形状实例。 因此,任何限制都必须在运行时完成,或者对类型施加额外的约束。 我认为运行时检查最优雅的解决方案就像是
type shape = ...
static member (-) (a,b) =
match (a,b) with
|Point(c,d),Point(e,f) -> ...
|Point(c,d),Vector(e,f) -> ...
| _ -> failwith "Can't add these shapes"
或者,您可以更改形状以将点和矢量作为不同DU的子类型,如下所示
type addable = |Point of point |Vector of point
然后相应地修改shape
。
我会做以下事情:
type PointT = double * double
type Shape =
| Point of PointT
| Line of PointT * PointT
| Vector of PointT
| Circle of PointT * double
with
member this.ToString = function
| Point (x,y) -> sprintf "(%f; %f)" x y
| Vector (x,y) -> sprintf "(%f; %f)" x y
| Line ((x0,y0),(x1,y1)) -> sprintf "(%f; %f)->(%f; %f)" x0 y0 x1 y1
| Circle ((x0,y0),radius) -> sprintf "(%f; %f)r%f" x0 y0 radius
let inline (-) (p0 : Shape) (p1 : Shape) : Shape option =
match p0, p1 with
| Point(x0, y0), Point(x1, y1) -> Some(Vector(x0 - x1, y0 - y1))
| _ -> None
let inline (+) (p0 : Shape) (p1 : Shape) : Shape option =
match p0, p1 with
| Point(x0, y0), Vector(x1, y1) -> Some(Point(x0 + x1, y0 + y1))
| _ -> None
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.