左箭头 <- 在 do 块外意味着什么?

What does left arrow <- mean outside a do block?

我最近遇到了下面的代码,这让我很困扰

lowerSafeForeignCall dflags block
| (entry, middle, CmmForeignCall { .. }) <- blockSplit block
= do
 -- do block stuffs
 -- Block doesn't end in a safe foreign call:
| otherwise = return block

这段代码来自 https://phabricator.haskell.org/rGHCb0534f78a73f972e279eed4447a5687bd6a8308e

在文件 compiler/cmm/CmmLayoutStack.hs

第 983 行

我真的很想知道这是什么 <- 第二行。 我相信 lowerSafeForeignCall 是一个函数,| 和 'otherwise' 表明这个函数使用了守卫。所以

(entry, middle, CmmForeignCall { .. }) <- blockSplit block

必须是布尔类型。但是 <- 在任何 do 块之外。 我在网上做了一些搜索,但仍然没有关于这种用法的任何线索。

这是一个pattern guard [Haskell-wiki]。自 Haskell'10 以来,守卫是限定符列表。限定符可以是条件(就像在旧守卫中一样),模式守卫.

Haskell 将因此(懒惰地)评估箭头右侧的表达式 <- 并旨在将其与箭头左侧的模式相匹配。如果成功,那么守卫(守卫的那部分)就成功了。如果守卫的所有部分都成功,那么规则"fires".

在这种特定情况下,模式中唯一可能失败的部分是三元组的第三项是 not 一个 CmmForeignCall 数据构造函数.此外,通过使用这种模式保护,我们当然可以在表达式主体中使用 entrymiddle

那是 pattern guard:

guard       →   pat <- infixexp      (pattern guard)

[...]

A guard has one of the following forms:

  • pattern guards are of the form p <- e, where p is a pattern (see Section 3.17) of type t and e is an expression type t. They succeed if the expression e matches the pattern p, and introduce the bindings of the pattern to the environment.

普通守卫仅限于布尔检查,模式守卫可以匹配任意模式并定义局部变量。 (在您的情况下 entrymiddleCmmForeignCall 的内容将直接在函数体中可用。)

您可以将布尔守卫视为等同于具有 True:

模式的模式守卫
| expr

效果像

| True <- expr