使用 as 语法进行惰性模式匹配的语法
Syntax for lazy pattern matching with `as` syntax
在(原版)GHCi 8.6.5 中,以下函数完全有效:
f xs@ ~(x:xt) = xs
如果我现在在 9.0.1 中做同样的事情,我会得到一个错误
Suffix occurrence of @. For an as-pattern, remove the leading whitespace.
仅仅去掉@
和~
之间的白色space似乎是不够的,因为那样@~
会被解释为运算符,所以唯一的我发现的有效变体是
f xs@(~(x:xt)) = xs
我想知道以下内容,但我在更改说明中找不到答案:
- 从 8.6.5 到 9.0.1 的具体变化是什么引入了这种不兼容性?
xs@(~(x:xt))
真的是编写此模式的最佳方法吗?还是有更好的方法?
描述了 GHC 9.0 中对 ~ 和 @ 处理的更改 here。引用迁移指南:
GHC 9.0 implements Proposal 229, which means that the !, ~, and @ characters are more sensitive to preceding and trailing whitespace than they were before. As a result, some things which used to parse one way will now parse differently (or throw a parse error).
加上括号(variable@(~pattern)
)是一个很好的解决办法。或者,您可以使用 let
或 where
绑定,或单独的惰性 case
:
-
rehead :: a -> [a] -> [a]
rehead x' xs0 = x' : xs
where
_x : xs = xs0
-
rehead :: a -> [a] -> [a]
rehead x' xs0 = let
_x : xs = xs0
in x' : xs
-
{-# Language PatternGuards #-}
rehead :: a -> [a] -> [a]
rehead x' xs0
| let _x : xs = xs0
= x' : xs
如果您想在后续守卫中使用这些绑定,这将非常有用。
-
rehead :: a -> [a] -> [a]
rehead x' xs0 = case xs0 of
~(_x : xs) -> x' : xs
所有这些选项都是最懒惰的:
head (rehead 5 [1, 2])
- =
head (rehead 5 [])
- =
head (rehead 5 undefined)
- =
5
如果您使用 {-# Language Strict #-}
,则必须将 let
/where
绑定写为 ~(_x : xs) = xs0
以允许 []
,并且列表参数绑定为 ~xs0
以允许 undefined
;要使用 case
获得 irrefutable 模式(不仅仅是懒惰),您必须编写 ~(~(_x : xs))
.
在(原版)GHCi 8.6.5 中,以下函数完全有效:
f xs@ ~(x:xt) = xs
如果我现在在 9.0.1 中做同样的事情,我会得到一个错误
Suffix occurrence of @. For an as-pattern, remove the leading whitespace.
仅仅去掉@
和~
之间的白色space似乎是不够的,因为那样@~
会被解释为运算符,所以唯一的我发现的有效变体是
f xs@(~(x:xt)) = xs
我想知道以下内容,但我在更改说明中找不到答案:
- 从 8.6.5 到 9.0.1 的具体变化是什么引入了这种不兼容性?
xs@(~(x:xt))
真的是编写此模式的最佳方法吗?还是有更好的方法?
描述了 GHC 9.0 中对 ~ 和 @ 处理的更改 here。引用迁移指南:
GHC 9.0 implements Proposal 229, which means that the !, ~, and @ characters are more sensitive to preceding and trailing whitespace than they were before. As a result, some things which used to parse one way will now parse differently (or throw a parse error).
加上括号(variable@(~pattern)
)是一个很好的解决办法。或者,您可以使用 let
或 where
绑定,或单独的惰性 case
:
-
rehead :: a -> [a] -> [a] rehead x' xs0 = x' : xs where _x : xs = xs0
-
rehead :: a -> [a] -> [a] rehead x' xs0 = let _x : xs = xs0 in x' : xs
-
{-# Language PatternGuards #-} rehead :: a -> [a] -> [a] rehead x' xs0 | let _x : xs = xs0 = x' : xs
如果您想在后续守卫中使用这些绑定,这将非常有用。
-
rehead :: a -> [a] -> [a] rehead x' xs0 = case xs0 of ~(_x : xs) -> x' : xs
所有这些选项都是最懒惰的:
head (rehead 5 [1, 2])
- =
head (rehead 5 [])
- =
head (rehead 5 undefined)
- =
5
如果您使用 {-# Language Strict #-}
,则必须将 let
/where
绑定写为 ~(_x : xs) = xs0
以允许 []
,并且列表参数绑定为 ~xs0
以允许 undefined
;要使用 case
获得 irrefutable 模式(不仅仅是懒惰),您必须编写 ~(~(_x : xs))
.