模式匹配中 as 的范围

Extent of `as` in pattern matching

给定一个从列表中删除连续重复项的函数

let rec compress l =
  match l with
  | [] -> []
  | [x] -> [x]
  | x :: (y :: _ as t) -> if x = y then compress t else x :: compress t;;

产生正确的结果

compress ["a"; "a";"b";"c";"c"] ;;
- : string list = ["a"; "b"; "c"]

但是如果我将 x :: (y :: _ as t) 改为 x :: (y :: t),那么我会得到不正确的结果

compress ["a"; "a";"b";"c";"c"] ;;
- : string list = ["b"; "c"]

这是怎么回事?我无法理解声明 _ as t 如何改变函数的输出。直觉上,我会认为它们是等效的语句(:: _ as t:: t),但似乎它们不是。

有人可以详细说明吗?

它们不等价,因为 as 尽可能向左延伸,所以

x :: (y :: ys as t)

变量 t 绑定到 y::ys 而不仅仅是 ys