common surprise对于刚入门的 F# 程序员来说,以下是不完全匹配的事实:
let x, y = 5, 10
match something with
| _ when x < y -> "Less than"
| _ when x = y -> "Equal"
| _ when x > y -> "Greater than"
但我刚刚遇到了一个让我感到惊讶的情况。下面是一小段示例代码来演示它:
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]"
此版本
describe
函数产生了“不完整的模式匹配此表达式”警告,即使模式匹配实际上是完整的。没有可能的树不会被该模式匹配匹配,这可以通过删除具有 when
的匹配的特定分支来看到。其中的表达:let describe tree =
match tree with
| Leaf n -> sprintf "Leaf containing %d" n
| Branch subTree ->
sprintf "Normal tree with sub-tree %A" subTree
此版本
describe
返回 sapling
的“普通树”字符串和 twoLeafTree
树木。在
match
的情况下表达式只包含 when
表达式(如第一个示例,其中比较 x
和 y
),F# 编译器可能无法判断匹配是否完整是合理的。毕竟x
和 y
可能是具有“奇怪”的比较和相等实现的类型,其中这三个分支都不为真。*但在像我这样的情况下
describe
函数,为什么 F# 编译器不查看模式,说“如果所有 when
表达式计算为 false
,仍然会有完整匹配”并跳过“不完整模式匹配”警告?此处显示此警告是否有某些特定原因,还是只是 F# 编译器在这里有点简单并由于其代码不够复杂而给出误报警告的情况?* 其实可以设置
x
和 y
值使得 x < y
, x = y
, 和 x > y
都是假的,没有超出标准 .Net 类型系统的“正常”范围。作为特别奖励问题/谜题,x
的这些值是多少?和 y
?不需要自定义类型来回答这个难题;您所需要的只是标准 .Net 中提供的类型。
最佳答案
在 F# match
语法,when
守卫适用于在它之前列举的所有情况,而不仅仅是最后一个。
在您的特定场景中,守卫 when saplingsGetSpecialTreatment
适用于两者 Leaf n
和 Branch [Leaf n]
案件。因此,对于 tree = Leaf 42 && saplingsGetSpecialTreatment = false
的情况,此匹配将失败。
以下将是完整的,因为 Leaf
case 现在有自己的分支:
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
关于f# - 当两个模式共享一个 `when` 子句时不完整的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43455264/