2017-07-25 94 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

这确实是另一个很好的解决方案,谢谢你的回答,有点晚了,因为我已经接受了第一个,但是这真的很好,并且由于更好地选择了活动模式,所以可读性更高。 –