Incomplete pattern matching when two patterns share the `when` clause

A common surprise for beginner F # programmers is that the following is an incomplete match:

let x, y = 5, 10
match something with
| _ when x < y -> "Less than"
| _ when x = y -> "Equal"
| _ when x > y -> "Greater than"

But I just ran into a situation that surprised me. Here is a small sample code for demonstration:

type Tree =
| Leaf of int
| Branch of Tree list

let sapling = Branch [Leaf 1]  // Small tree with one leaf
let twoLeafTree = Branch [Leaf 1; Leaf 2]

let describe saplingsGetSpecialTreatment tree =
    match tree with
    | Leaf n
    | Branch [Leaf n] when saplingsGetSpecialTreatment ->
        sprintf "Either a leaf or a sapling containing %d" n
    | Branch subTree ->
        sprintf "Normal tree with sub-tree %A" subTree

describe true sapling // Result: "Either a leaf or a sapling containing 1"
describe false sapling // Result: "Normal tree with sub-tree [Leaf 1]"
describe true twoLeafTree // Result: "Normal tree with sub-tree [Leaf 1; Leaf 2]"
describe false twoLeafTree // Result: "Normal tree with sub-tree [Leaf 1; Leaf 2]"

This version of the function describeraised the warning “Incomplete pattern matching with this expression”, although the pattern matching is essentially complete. There are no possible trees that will not be matched with this pattern match, as can be seen from the removal of the particular matching branch in which the expression was when:

let describe tree =
    match tree with
    | Leaf n -> sprintf "Leaf containing %d" n
    | Branch subTree ->
        sprintf "Normal tree with sub-tree %A" subTree

This version describereturns the string "Normal tree" for trees saplingand twoLeafTree.

, match when (, , x y ), , F # . , x y "" , . *

, describe, F # , : " when false, " ? - , , , F # , ?

* , x y , x < y, x = y x > y , "" .Net type system. /, x y? , ; , , , .Net.

+4
2

F # match when , , .

when saplingsGetSpecialTreatment Leaf n Branch [Leaf n]. , , tree = Leaf 42 && saplingsGetSpecialTreatment = false

:

let describe saplingsGetSpecialTreatment tree =
    match tree with
    | Leaf n ->
        sprintf "Either a leaf or a sapling containing %d" n
    | Branch [Leaf n] when saplingsGetSpecialTreatment ->
        sprintf "Either a leaf or a sapling containing %d" n
    | Branch subTree ->
        sprintf "Normal tree with sub-tree %A" subTree
+8

. y = 3, ,

let f y x = 
  match x with
  | 0 
  | 1 
  | 2 when y = 3 -> "a"
  | 0
  | 1
  | 2            -> "b"
  | _            -> "c"

[0 .. 3] |> List.map (f 3)
[0 .. 3] |> List.map (f 2)

FSI

val f : y:int -> x:int -> string

> val it : string list = ["a"; "a"; "a"; "c"]

> val it : string list = ["b"; "b"; "b"; "c"]

, ? .

:

let f2 y x =
  match x,y with
  | 0,3
  | 0,3
  | 0,3 -> "a"
  | 0,_
  | 1,_
  | 2,_ -> "b"
  | _ -> "c"

[0 .. 3] |> List.map (f2 3)
[0 .. 3] |> List.map (f2 2)

... :

let f3 y x = x |> function | 0 | 1 | 2 when y = 3 -> "a"
                           | 0 | 1 | 2 -> "b"
                           | _ -> "c"
+1

Source: https://habr.com/ru/post/1674983/


All Articles