A 共同的惊喜 https://stackoverflow.com/q/18691622/2314532对于 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
函数产生了“此表达式的模式匹配不完整”警告,即使模式匹配实际上是完整的。没有可能的树不会被该模式匹配所匹配,如以下所示removing比赛的特定分支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
and twoLeafTree
trees.
在这种情况下match
表达式仅包含when
表达式(如第一个示例,其中x
and y
正在比较),F# 编译器可能无法判断匹配是否完整是合理的。毕竟,x
and y
might是具有比较和相等的“奇怪”实现的类型,其中这三个分支都不成立。*
但在像我这样的情况下describe
函数,为什么 F# 编译器不查看该模式,说“如果所有when
表达式评估为false
,仍然会有一个完整的匹配”并跳过“不完整的模式匹配”警告?这里出现此警告是否有某些特定原因,或者只是 F# 编译器在这里有点简单化并给出了一个情况因为代码不够复杂而出现误报警告?
* 其实可以设置x
and y
值使得x < y
, x = y
, and x > y
are allfalse,而不会超出标准 .Net 类型系统的“正常”范围。作为一个特殊的奖励问题/谜题,这些值是什么x
and y
?不需要自定义类型来回答这个难题;您所需要的只是标准 .Net 中提供的类型。