2017-07-25 83 views
4

我是F#的新手,我試圖做一個複雜類型的簡單模式匹配,但我找不到這樣做的方式。查看下面的僞代碼來解釋我想要做的模式匹配。F#與複雜類型匹配

type Vector= {X:int; Y:int} 

let calculateDirection vector = 
match vector with 
| vector.X=0 && vector.Y>0 -> "N" // pseudo code 
| vector.X>0 && vector.Y>0 -> "NE" // pseudo code 
| vector.X>0 && vector.Y=0 -> "E" // pseudo code 
| vector.X>0 && vector.Y<0 -> "SE" // pseudo code 
| vector.X=0 && vector.Y<0 -> "S" // pseudo code 
| vector.X<0 && vector.Y<0 -> "SW" // pseudo code 
| vector.X<0 && vector.Y=0 -> "W" // pseudo code 
| vector.X<0 && vector.Y>0 -> "NW" // pseudo code 
| _ -> "Error" 

我讀了一些教程(https://fsharpforfunandprofit.com/posts/match-expression/),但它總是簡單的場景,並沒有幫助我很多。或者我只是不明白他們。

在此先感謝。

回答

4

,以配合記錄,您可以使用記錄匹配語法,就像檔案建設語法:

match vector with 
| { X = x; Y = y } -> sprintf "Vector (%d, %d)" x y 

可以結合起來,與警衛,太:

match vector with 
| { X = 0; Y = y } when y > 0 -> "N" 
| { X = x; Y = y } when x > 0 && y > 0 -> "NE" 
| { X = x; Y = 0 } when x > 0 -> "E" 
... 

但是這看起來有點醜陋。爲了幫助醜陋,你也可以構建你自己的匹配器(又稱「活動模式」) - 它們就像常規函數一樣,但可以用於匹配。他們有一種滑稽的語法定義的:

let (|Positive|_|) x = if x > 0 then Some() else None 
let (|Negative|_|) x = if x < 0 then Some() else None 

match vector with 
| { X = 0; Y = Positive } -> "N" 
| { X = Positive; Y = Positive } -> "NE" 
| { X = Positive; Y = 0 } -> "E" 
| { X = Positive; Y = Negative } -> "SE" 
... 
+1

謝謝,我用積極的方式解決方案,因爲它是確實好多了可讀性。 –

6

使用Active模式,你可以得到非常可讀的代碼是這樣:這是正常使用

type Vector= {X:int; Y:int} 

let (|West|_|) v = if v.X < 0 then Some() else None 
let (|East|_|) v = if v.X > 0 then Some() else None 
let (|North|_|) v = if v.Y > 0 then Some() else None 
let (|South|_|) v = if v.Y < 0 then Some() else None 

let calculateDirection = function 
    | North & East -> Some "NE" 
    | North & West -> Some "NW" 
    | North -> Some "N" 
    | South & East -> Some "SE" 
    | South & West -> Some "SW" 
    | South -> Some "S" 
    | East -> Some "E" 
    | West -> Some "W" 
    | _ -> None 
+0

這確實是另一個很好的解決方案,謝謝你的回答,有點晚了,因爲我已經接受了第一個,但是這真的很好,並且由於更好地選擇了活動模式,所以可讀性更高。 –