2016-03-15 96 views
2

为什么没有图案的分配值匹配认可为什么没有图案的分配值匹配认可

我收到警告,当我尝试在值称为目标模式匹配:

[<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 

回答

8

match表达式,该规则

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

无条件匹配并结合k到一个名称target其阴影的现有定义。这意味着永远不会达到以下条款。您可以使用条件匹配:

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

根据Pattern Matchingtarget可变模式,所以阴影原目标值。

模式匹配是有用的解构匹配的对象,对于简单的测试是可取的(在我看来)。

模式匹配的用例是如果你想测试几个案例。您也可以使用active patterns代替when guard

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