守护语法中的逗号有什么作用?

时间:2017-10-01 06:37:47

标签: haskell syntax guard-clause pattern-guards

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

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编程中提到的这个语法来自第一原则,如果是,那么在哪里?我记不起来了解它。)

2 个答案:

答案 0 :(得分:28)

Haskell 2010 section 3.13, Case Expressions中描述了警卫  (该部分是关于案例表达式,而不是顶级声明,但可能是语义相同):

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

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

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

守卫中的逗号是不常见的(根据我的经验,至少)我将此功能描述为Haskell琐事 - 完全没有必要写(或者,大部分是阅读)Haskell。我怀疑 Haskell Programming from first principles 因为这个原因而省略了它。

答案 1 :(得分:2)

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

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

真正的用处在于允许你在一个保护子句中进行模式匹配。句法变化还有一个副作用,即允许你使用逗号将几个布尔术语加在一起。

(我个人真的不喜欢这个扩展,我有点震惊它使它成为官方规范,但我们是......)