我是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/),但它总是很简单,并没有多大帮助。或者我只是不清楚它们。
提前致谢。
答案 0 :(得分:6)
使用活动模式,您可以获得非常易读的代码:
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
答案 1 :(得分: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"
...