创建单例列表的两个函数之间的差异

时间:2013-01-25 21:19:06

标签: haskell hlint

在我的程序上运行hlint时,它报告

错误
\x -> [x]

并建议替代形式

(: [])

根据关于第一种形式的hlint有什么错误,因此为什么我应该使用(不太可读)第二种形式?

修改

(明确地向问题添加了hlint)

在词汇的观点上,我的问题不在于差异是什么(我确实理解它们两者)。我的问题是我不明白为什么hlint将其标记为错误。有没有例如懒惰的差异?此外,为什么先前认为hlint为错误,而\x -> Just x仅引发警告。

3 个答案:

答案 0 :(得分:14)

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

  

每个提示都有严重级别:

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

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

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

答案 1 :(得分:12)

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

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

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

答案 2 :(得分:7)

我可能会考虑使用returnpure

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

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

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