10

在我的程序上运行 hlint 时,它报告了一个错误

\x -> [x]

并提出了另一种形式

(: [])

根据关于第一种形式的 hlint有什么错误,因此我为什么要使用(可读性较差的)第二个选项?

编辑

(在问题中明确添加了 hlint)

我的问题不在于从词汇的角度来看有什么区别(我确实理解它们)。我的问题是我不明白为什么 hlint 将其标记为错误。例如,懒惰有区别吗?此外,为什么hlint之前的想法是错误\x -> Just x的,而只会提出警告。

4

3 回答 3

15

一个常见问题,我刚刚在HLint 手册中添加了一个答案。它说:

每个提示都有一个严重级别:

  • 错误 - 例如concat (map f x)建议concatMap f x作为“错误”严重性提示。从风格的角度来看,您应该始终将concat和的组合map替换为concatMap。请注意,这两个表达式是等效的 - HLint 报告的是样式错误,而不是代码中的实际错误。
  • 警告- 例如x !! 0建议head x作为“警告”严重性提示。通常head是表达列表第一个元素的一种更简单的方法,尤其是在您以归纳方式处理列表时。但是,在表达式f (x !! 4) (x !! 0) (x !! 7)中,将中间参数替换为 head 会使模式更难遵循,并且可能是个坏主意。警告提示通常是值得的,但不应盲目应用。

错误和警告之间的区别是个人品味之一,通常是我的个人品味。如果你已经对 Haskell 风格有很好的理解,你应该忽略其中的区别。如果您是初学者 Haskell 程序员,您可能希望在警告提示之前关注错误提示。

虽然区别在于个人品味,但有时我会改变主意。查看此线程中的两个示例,(:[])似乎是一个相对“复杂”的提示-您正在分解 to 的语法糖[x]x:[]如果您从不进行模式匹配,则在某些方面将列表的抽象剥离为通用容器它。相比之下\x -> Just xJust总是似乎是个好主意。因此,在 HLint-1.8.43(刚刚发布)中,我将第一个警告,第二个错误。

于 2013-01-27T22:43:10.297 回答
12

没有真正的区别。HLint 关注风格问题;最终,它们只是关于如何使您的代码看起来更好的提示。

通常,将 lambda 与类似的构造函数或函数一起使用是多余的,并且会使代码更难阅读。举个极端的例子,以构造函数 likeJust为例:Just比较\ x -> Just x. 这些是等价的,但第二个版本肯定会让事情变得更加混乱!作为一个更接近的例子,大多数人会选择(+ 1)over \ x -> x + 1

在您的特定情况下,这是一个不同的故事,因为列表具有特殊的语法。因此,如果您\ x -> [x]更喜欢该版本,请保留它。但是,一旦您习惯了操作符部分,您可能会发现该(: [])版本很容易阅读(如果不是更容易的话),因此即使现在也要考虑使用它。

于 2013-01-25T21:27:40.103 回答
7

我可能会考虑使用returnorpure为此:

ghci> return 0 :: [Int]
[0]

ghci> import Control.Applicative
ghci> pure 0 :: [Int]
[0]

我需要包含类型注释 ( :: [Int]) 因为我在 GHCi 中工作。在一堆其他代码中间,您可能不需要它。

于 2013-01-26T09:16:12.187 回答