为什么在识别的指定值上没有模式匹配

时间:2016-03-15 14:52:02

标签: f#

为什么在识别的指定值上没有模式匹配

当我尝试对名为target的值进行模式匹配时收到警告:

[<Test>]
let ``set center cell to alive``() =
    // Setup
    let target = (2,2)

    let grid = createGrid 9 |> Map.map (fun k v -> 
                                            match k with
                                            | target -> { v with Status=Alive }
                                            | _      -> v)
    // Test
    let center = grid |> getStatus (2,2)

    // Verify
    center |> should equal Alive

警告指向:

| target -> { v with Status=Alive }
| _      -> v)

特别是:

| _      -> v)

警告是:

  

永远不会达到这条规则。

这迫使我不使用目标,而是对值进行硬编码以解决警告:

[<Test>]
let ``set center cell to alive``() =
    // Setup
    let grid = createGrid 9 |> Map.map (fun k v -> 
                                            match k with
                                            | (2,2) -> { v with Status=Alive }
                                            | _     -> v)
    // Test
    let center = grid |> getStatus (2,2)

    // Verify
    center |> should equal Alive

有人可以解释为什么我不能这样做吗?

完整代码:

type Status = Alive | Dead
type Cell = { X:int; Y:int; Status:Status }

let isNeighbor cell1 cell2 =

    let isAbsNeighbor v1 v2 =
        match abs (v1 - v2) with
        | 0 | 1 -> true
        | _     -> false

    let isValueNeighbor v1 v2 =
        match v1 >= 0
          &&  v2 >= 0 with
        | true  -> isAbsNeighbor v1 v2
        | _     -> isAbsNeighbor v2 v1

    match cell1.X <> cell2.X
      ||  cell1.Y <> cell2.Y with
    | true ->   isValueNeighbor cell1.X cell2.X
             && isValueNeighbor cell1.Y cell2.Y
    | _    -> false

let createGrid rowCount = 

    [for x in 1..rowCount do
        for y in 1..rowCount do
            yield { X=x; Y=y; Status=Dead } ]
    |> List.map (fun c -> (c.X, c.Y), { X=c.X; Y=c.Y; Status=Dead })
    |> Map.ofList

let getStatus coordinate (grid:Map<(int * int), Cell>) =

    match grid.TryFind coordinate with
    | Some cell -> cell.Status
    | None      -> Dead

2 个答案:

答案 0 :(得分:8)

match表达式中,规则

match k with
| target -> { v with Status=Alive }

无条件地匹配并将k绑定到名称target,该名称隐藏现有定义。这意味着永远不会达到以下条款。您可以使用条件匹配:

match k with
| t when t = target -> { v with Status = Alive }
| _ -> v

答案 1 :(得分:0)

根据Pattern Matchingtarget变量模式,因此它会隐藏原始目标值。

模式匹配对于匹配对象的解构非常有用,因为简单的测试if-else是可取的(在我看来)。

如果要测试多个案例,则用于模式匹配的用例。您可以使用when guard代替active patterns

let (|Eq|_|) expected actual =
    if expected = actual then Some()
    else None

let target = (2,2)

let attempt = (3,2)

match attempt with
| Eq target -> Some "Bulls eye"
| (2, _) -> Some "Almost"
| t when fst t > 20 -> Some "Quite the contrary"
| _ -> None