为什么这在Haskell模式匹配时是一个有用的警告&引用;“已定义但未使用”;
定义函数的多个模式匹配时,例如:为什么这在Haskell模式匹配时是一个有用的警告&引用;“已定义但未使用”;,haskell,pattern-matching,warnings,Haskell,Pattern Matching,Warnings,定义函数的多个模式匹配时,例如: 1: takeTree 0 tree = Leaf 2: takeTree levels (Leaf) = Leaf 3: takeTree levels (Branch value left right) = Branch value (takeTree... 我特别收到两条警告: Source.hs:1:警告:已定义但未使用:`tree' Source.hs:2:警告
1: takeTree 0 tree = Leaf
2: takeTree levels (Leaf) = Leaf
3: takeTree levels (Branch value left right) = Branch value (takeTree...
我特别收到两条警告:
Source.hs:1:警告:已定义但未使用:`tree'
Source.hs:2:警告:已定义但未使用:`levels'
不过,我并不认为这些是有用的警告。如果我的代码是:
1: takeTree 0 _ = Leaf
2: takeTree _ (Leaf) = Leaf
3: takeTree levels (Branch value left right) = Branch value (takeTree...
修复了这些警告,我现在发现它的可读性要差得多,并且混淆了我所期望的输入值的语义
在我的详尽模式中,每个参数实际上至少使用了一次,为什么
在这里被定义但没有被使用
是一个合理的警告?编译器试图建议您使用某种类型的编码。如果你不喜欢(很公平),有一种方法可以避免这个问题。例如,见:
至于问题的实质(这是否是一个有用的警告):在这种情况下命名变量的缺点是,它表明这些名称对编译器来说是有意义的,而实际上它们不是。正如你正确指出的那样,好处在于它们对人类有意义。基本上,这是一种权衡,这是相当主观的。重要的是,如果需要,您可以获得所需的行为。我犯了此警告指出的编码错误。简化示例:
fun x xs = go xs
where
go [] = ...
go (y:xs') = f y (go xs)
当然,递归调用应该将xs'
作为参数,并且“已定义但未使用”警告将捕获该参数。对我来说,这是值得为未使用的比赛使用的不便
编译器无法猜测您的意图,并且您在另一个匹配中使用参数并不意味着您不打算在生成警告的匹配中使用它。毕竟,您本可以使用树
,因此您没有使用的警告是合理的
另请参见Ben的答案:您可以使用
\u name
来使用一个名称,但仍会抑制警告。如果某个东西足够重要,那么它必须足够重要,才能使用,这一假设在许多编码样式中都是合理的
但你也可以吃蛋糕:
takeTree 0 _tree = Leaf
takeTree _levels (Leaf) = Leaf
takeTree levels (Branch value left right) = Branch value (takeTree...
名称中的前导下划线向人类读者和编译器发出信号,表示该名称不打算在这个等式中使用,但长度超过一个下划线的名称仍然可以向人类传达更多的含义。而这种错误实际上并不罕见,也不是微不足道的。因为prime变量通常与非prime变量非常相似,所以它从来都不是类型错误,而且在运行时调试中通常很难发现,就像很难发现缺少的
“
本身一样+1.