在我正在阅读的代码库中,我发现了一个像这样的函数声明(缺少某些部分):
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编程中提到的这个语法来自第一原则,如果是,那么在哪里?我记不起来了解它。)
答案 0 :(得分:28)
Haskell 2010 section 3.13, Case Expressions中描述了警卫 (该部分是关于案例表达式,而不是顶级声明,但可能是语义相同):
guards → | guard1, …, guardn (n ≥ 1)
guard → pat <- 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
真正的用处在于允许你在一个保护子句中进行模式匹配。句法变化还有一个副作用,即允许你使用逗号将几个布尔术语加在一起。
(我个人真的不喜欢这个扩展,我有点震惊它使它成为官方规范,但我们是......)