14

在“Programming F#”中,我遇到了这样的模式匹配(我简化了一点):

let rec len list = 
  match list with
  | [] -> 0
  | [_] -> 1
  | head :: tail -> 1 + len tail;;

实际上,我知道最后一场比赛可以识别列表的头部和尾部。从概念上讲,我不明白它为什么起作用。据我了解, :: 是 cons 运算符,它在列表的头部位置附加一个值,但在我看来,它不像在这里被用作运算符。我是否应该将此理解为列表的“特殊语法”,其中 :: 被解释为运算符或取决于上下文的“匹配模式”?或者是否可以使用其他运算符将相同的想法扩展到列表以外的类型?

4

3 回答 3

14

这是列表的特殊语法。因此,您可以将list类型视为有区别的联合:

type list<'T> =         // '
    | Nil
    | Cons of 'T * list<'T>

除了有特殊的语法使Nilbe[]Cons(h,t)be h::t。然后它只是一个有区别的联合上的正常模式匹配。这有帮助吗?

(可能另见此博客条目。)

于 2010-05-17T04:17:37.363 回答
12

除了Brian的回答,还有几点值得注意。该h::t语法既可以用作运算符也可以用作模式:

let l = 1::2::[]                    // As an operator
match l with x::xs -> 1 | [] -> 0   // As a pattern

这意味着它是一个有点特殊的构造,因为其他运算符(例如+)不能用作模式(用于将结果分解回运算符的参数) - 显然,对于+,这将是模棱两可的。

此外,该模式[_]很有趣,因为它是嵌套模式的一个示例。它组成:

  • _- 下划线模式,匹配任何值且不绑定任何符号
  • [ <pattern> ]- 单元素列表模式,它匹配具有单个元素的列表并将列表的元素与嵌套的<pattern>.

您还可以编写match 1::[] with | [x] -> xwhich 将返回单个元素的值(在本例中为 1)。

于 2010-05-17T13:23:01.617 回答
5

它被用作格式化程序或正式pattern地,`list' 匹配三种模式:

[] 表示列表为空

[_] 表示列表只有一个元素,因为你不关心元素是什么,所以简单地把 _ 放在那里,你也可以使用 [a]。

head::tail 意味着列表确实有两部分:头部和尾部。

您可以将 F# 模式匹配视为一种强大的 if then else 结构。

于 2010-05-17T04:18:49.140 回答