2011-08-18 74 views
2

讓我們考慮以下Point記錄類型:模式匹配記錄類型

type Point = { x:int; y:int } 

我想提出一個謂語,告訴我一個給定的點是否在有效的區域。

let insideBounds p = 
    let notInside c = c < 0 || c > 100 
    match p with 
    | {x=i; y=_} when notInside i -> false 
    | {x=_; y=j} when notInside j -> false 
    | _       -> true 

這工作,但我不知道是否有實現其作爲insideBounds簽名

let insideBounds {x=i; y=j} 

代替,仍利用模式匹配的相同結果的另一種方式?

回答

6

可以定義一個有源圖案測試一個值是否爲指定作爲自變量的範圍內:

let (|InRange|_|) (min, max) v = 
    if v >= min && v <= max then Some() else None 

然後,定義insideBounds這樣的:

let insideBounds = function 
    | { x = InRange (0, 100); y = InRange (0, 100) } -> true 
    | _ -> false 

第一當x anad y成員都在指定範圍內時,大小寫匹配。活動模式返回option unit,這意味着它不綁定任何值。 (0, 100)是輸入參數,當值(xy)在該範圍內時,模式匹配。

(在其他情況下`比賽10 INRANGE(0

+0

然後可以用函數式樣式輕鬆地重寫:let insideRounds {x = i; y = j} = let inRange =( (| InRange | _ |)(0,100)>> Option.isSome); inRange i && inRange j' :-) – Daniel

+0

@Tomas很酷。模式匹配語句的行爲類似於Maybe模式。 – gradbot

4

當然。

type Point = { x:int; y:int } 

let insideBounds {x=i; y=j} = 
    let notInside c = c < 0 || c > 100 
    not (notInside i || notInside j) 

我建議你顛倒邏輯,使其更清晰:

let insideBounds {x=i; y=j} = 
    let isInside c = c >= 0 && c <= 100 
    isInside i && isInside j 

作爲一般規則,它是布爾函數/屬性等更是肯定的。這樣,否定就保留了它的消極性,可以這麼說。

+0

對不起,我不太清楚,你的解決方案是遠遠比我上面顯示更好的(實際上,我是用* *正好相同解決方案,正如你在我自己的代碼中所展示的那樣)我只是在試圖理解如何完成與那個函數簽名的模式匹配 –

+0

重要的是,模式匹配發生在很多地方,包括函數參數。 msdn.microsoft.com/en-us/library/dd547125.aspx(請參閱備註) – Daniel