【问题标题】:Difference between two functions creating a singleton list创建单例列表的两个函数之间的区别
【发布时间】:2013-01-25 21:19:06
【问题描述】:

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

\x -> [x]

并建议了替代形式

(: [])

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

编辑

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

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

【问题讨论】:

  • 是的(:[])(“机器人”)对初学者来说很奇怪;当我第一次看到它时,它确实让我绊倒了。但现在它只是我词汇表中的另一个习语——就像复数一个变量名(例如xs)或使用一个部分来翻转一个函数(例如(`Map.member` m))

标签: haskell hlint


【解决方案1】:

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

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

  • 错误 - 例如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 程序员,您可能希望在警告提示之前关注错误提示。

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 感谢您的回答。虽然对我来说仍然存在一个问题(这可能是最有趣的部分),但为什么 hlint 认为这是一个错误而不是警告?我已经编辑了问题以使其更加清晰,并添加了在您的示例上运行 hlint 的结果。
    • hlint 认为错误和警告的内容只是 Neil Mitchell 的判断。不要深入其中。
    • @augustss,好的,当这是标准时,我确实不应该过多关注错误和警告之间的差异。
    【解决方案3】:

    我可能会考虑为此使用return 或pure:

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

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

    【讨论】:

    • 虽然有时很想这样做,但我认为与使用其他任何一种解决方案相比,它使发生的事情不太清楚。
    • 我还记得那天我发现return :: [x] 是\ x -> [x]。我希望 Haddock 有一个很好的方法来记录这些有用的事实......
    猜你喜欢
    • 1970-01-01
    • 2011-09-06
    • 2014-11-04
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    相关资源
    最近更新 更多