[英]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.