luk*_*san 6 f# pattern-matching
考虑以下废话lambda:
function
| [] -> "Empty list"
| hd::tl -> "Not so empty list"
Run Code Online (Sandbox Code Playgroud)
这很好用.现在我重写如下:
function
| [] -> "Empty list"
| hd::tl & l -> "Not so empty list"
Run Code Online (Sandbox Code Playgroud)
同样,出于无意义的原因(并且我知道我可以通过使用as代替而实现相同的效果&,但这都与代码 - 高尔夫问题有关,这与此问题无关).现在F#编译器告诉我:
警告FS0025:此表达式上的不完整模式匹配.例如,值"[]"可以指示模式未涵盖的情况.
这没有任何意义 - 我明确地处理[]了第一条规则中的情况.我没有看到从第一个功能到第二个功能的变化[]; 函数的第二个规则都不匹配它,但只有第二个函数给出警告.我所做的只是添加一个匹配任何东西的附加模式.
当然,使用空列表调用第二个函数确实成功.
是否有正确的原因发生此警告,或者F#模式验证是否只是有一些怪癖?当使用更高级的模式时,我可以看到有这样的情况,但这似乎是一个非常基本的模式.即使问题一般无法解决,似乎这种类型的情况也足够普遍,值得在编译器中进行特殊处理.
我认为F#编译器在这种情况下是实用的.
最后,第二条规则可以表示为输入列表的约束xs:
xs = hd :: tl && xs = l
Run Code Online (Sandbox Code Playgroud)
F#编译器似乎没有探索&&约束.这是合理的,因为约束可以是任意复杂的,并且使用&非常少见.
我们对部分活动模式有类似的问题:
let (|Empty|_|) = function
| [] -> Some()
| _ -> None
let (|NonEmpty|_|) = function
| _ :: _ -> Some()
| _ -> None
// warning FS0025
let f = function
| Empty -> "Empty list"
| NonEmpty -> "Not so empty list"
Run Code Online (Sandbox Code Playgroud)
要解决此问题,您可以:
as而不是&,这更合适,因为l它只是一个绑定.在末尾添加通配符模式以消除警告.我经常写
let f =
function
| hd::tl & l -> "Not so empty list"
| _ -> "Empty list"
Run Code Online (Sandbox Code Playgroud)使用禁止警告nowarn "25".