【问题标题】:What does a comma in the guard syntax do?保护语法中的逗号有什么作用?
【发布时间】:2018-03-12 14:26:15
【问题描述】:

在我正在阅读的代码库中,我发现了这样的函数声明(缺少某些部分):

filepathNormalise :: BS.ByteString -> BS.ByteString
filepathNormalise xs
    | isWindows, Just (a,xs) <- BS.uncons xs, sep a, Just (b,_) <- BS.uncons xs, sep b
    = '/' `BS.cons` f xs

逗号在这里有什么作用?

(仅作为奖励,如果有人很容易知道这一点:Haskell Programming from first principle 中是否提到了这种语法,如果有,在哪里?因为我不记得读过它。)

【问题讨论】:

  • 我猜它等同于逻辑和?但我可以想象,其他 haskell 初学者也会有同样的问题,因此我认为,在 stackoverflow 上提出这个问题可能会很好。
  • 即使您知道答案,也最好发布这个问题(如果是这样的话,可能连同答案一起发布)。
  • 更新the wiki

标签: haskell syntax guard-clause pattern-guards


【解决方案1】:

守卫在Haskell 2010 section 3.13, Case Expressions中描述 (该部分是关于 case 表达式,而不是顶级声明,但大概语义是相同的):

guards  →  | guard1, …, guardn      (n ≥ 1)
guardpat <- infixexp         (pattern guard)
        |  let decls               (local declaration)
        |  infixexp                (boolean guard)

对于每个受保护的表达式,逗号分隔的保护从左到右依次尝试。如果它们都成功了,那么相应的表达式将在使用警卫引入的绑定扩展的环境中进行评估。也就是说,由守卫(通过使用 let 子句或模式守卫)引入的绑定在以下守卫和相应表达式的范围内。如果任何一个守卫失败,则这个守卫表达式失败并尝试下一个守卫表达式。

在简单的情况下,逗号的作用类似于布尔。但是逗号更强大,因为每个守卫都可以引入新的绑定,供后续守卫使用(从左到右进行)。

守卫中的逗号并不常见(至少根据我的经验),我将这个功能描述为 Haskell 琐事——对于编写(或者,在大多数情况下,阅读)Haskell 完全没有必要。我怀疑 Haskell Programming from first principle 出于这个原因而忽略了它。

【讨论】:

  • 您引用了定义,但似乎错过了重要部分:“由警卫引入的绑定......在以下警卫的范围内”。如果将所有逗号替换为&amp;&amp;s,这当然是不可能的。例如,将case () of {() | x &lt;- 1, x == 1 -&gt; True}case () of {() | x &lt;- 1 &amp;&amp; x == 1 -&gt; True} 进行比较。原始问题中询问的代码甚至包括使用此功能。
  • @amalloy 确实。当涉及模式保护p &lt;- e 或让let x = e 参与时,此功能不是多余的。如果守卫只使用布尔表达式,那么逗号确实可以替换为&amp;&amp;。如果可能的话,我会说惯用的 Haskell 使用 &amp;&amp;
  • 啊,谢谢,是的,我很粗心。将进行适当的更正。
  • 我想说警卫中的逗号很常见。我一直在使用它们。如果您使用视图模式,它们可以避免,但我不喜欢这些。
【解决方案2】:

这种语法在 Haskell '98 中是不合法的;这是在 Haskell 2010 的语言规范中添加的。它是“模式保护”语言扩展的一部分。

https://prime.haskell.org/wiki/PatternGuards

真正的 用处在于允许您在保护子句中进行模式匹配。语法更改还有一个副作用,即允许您使用逗号将多个布尔术语“与”在一起。

(我个人非常不喜欢这个扩展,我对它进入官方规范感到有点震惊,但我们是……)

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 2010-09-14
    • 2010-09-08
    相关资源
    最近更新 更多