case expressions/list 推导式中的模式匹配
Pattern matching in case expressions/list comprehensions
为什么以下尝试在列表理解中进行模式匹配不起作用?
示例:同时替换术语数据类型中的原子。
数据类型:
data Term a
= Atom a
| Compound (Term a) (Term a)
deriving Show
原子的替换算法(如果有则选择第一个匹配的替换并忽略其余的):
subs :: [(Term a, Term a)] -> Term a -> Term a
subs subList term = case term of
atom@(Atom x) -> let substitutions =
[ s | s@(Atom x, _) <- subList ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)
部分测试数据:
subList = [((Atom 'a'), Compound (Atom 'b') (Atom 'c'))]
term1 = Atom 'a'
term2 = Atom 'x'
运行 该示例导致:
>: subs subList term1
Compound (Atom 'b') (Atom 'c')
这是期望的行为,并且
>: subs subList term2
Compound (Atom 'b') (Atom 'c')
这不是。
Strangley 显式匹配有效:
subs'' :: [(Term Char, Term Char)] -> Term Char -> Term Char
subs'' subList term = case term of
atom@(Atom _) -> let substitutions =
[ s | s@(Atom 'a', _) <- subList ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)
subs''' subList term = case term of
atom@(Atom _) -> let substitutions =
[ s | s@(Atom 'x', _) <- subList ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)
输入测试数据结果:
>: subs'' subList term1
或 >: subs'' subList term2
Compound (Atom 'b') (Atom 'c')
>: subs''' subList term1
或 >: subs''' subList term2
Atom 'x'
我错过了什么?
Haskell具有线性模式,这意味着模式中不能有重复的变量。此外,内部表达式中的模式变量会影响外部变量,而不是建立相同变量的相等性。
您正在尝试做这样的事情:
charEq :: Char -> Char -> Bool
charEq c c = True
charEq _ _ = False
但由于重复的变量,这是一个错误。如果我们将第二个 c
移动到内部表达式,它会编译,但它仍然无法按预期工作:
charEq :: Char -> Char -> Bool
charEq c d = case d of
c -> True
_ -> False
这里的内部 c
只是一个新变量,它遮蔽了外部 c
,所以 charEq
总是 returns True
.
如果我们想检查是否相等,我们必须显式使用 ==
:
subs :: [(Term a, Term a)] -> Term a -> Term a
subs subList term = case term of
atom@(Atom x) -> let substitutions =
[ s | s@(Atom x', _) <- subList, x == x' ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)
为什么以下尝试在列表理解中进行模式匹配不起作用?
示例:同时替换术语数据类型中的原子。
数据类型:
data Term a
= Atom a
| Compound (Term a) (Term a)
deriving Show
原子的替换算法(如果有则选择第一个匹配的替换并忽略其余的):
subs :: [(Term a, Term a)] -> Term a -> Term a
subs subList term = case term of
atom@(Atom x) -> let substitutions =
[ s | s@(Atom x, _) <- subList ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)
部分测试数据:
subList = [((Atom 'a'), Compound (Atom 'b') (Atom 'c'))]
term1 = Atom 'a'
term2 = Atom 'x'
运行 该示例导致:
>: subs subList term1
Compound (Atom 'b') (Atom 'c')
这是期望的行为,并且
>: subs subList term2
Compound (Atom 'b') (Atom 'c')
这不是。
Strangley 显式匹配有效:
subs'' :: [(Term Char, Term Char)] -> Term Char -> Term Char
subs'' subList term = case term of
atom@(Atom _) -> let substitutions =
[ s | s@(Atom 'a', _) <- subList ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)
subs''' subList term = case term of
atom@(Atom _) -> let substitutions =
[ s | s@(Atom 'x', _) <- subList ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)
输入测试数据结果:
>: subs'' subList term1
或 >: subs'' subList term2
Compound (Atom 'b') (Atom 'c')
>: subs''' subList term1
或 >: subs''' subList term2
Atom 'x'
我错过了什么?
Haskell具有线性模式,这意味着模式中不能有重复的变量。此外,内部表达式中的模式变量会影响外部变量,而不是建立相同变量的相等性。
您正在尝试做这样的事情:
charEq :: Char -> Char -> Bool
charEq c c = True
charEq _ _ = False
但由于重复的变量,这是一个错误。如果我们将第二个 c
移动到内部表达式,它会编译,但它仍然无法按预期工作:
charEq :: Char -> Char -> Bool
charEq c d = case d of
c -> True
_ -> False
这里的内部 c
只是一个新变量,它遮蔽了外部 c
,所以 charEq
总是 returns True
.
如果我们想检查是否相等,我们必须显式使用 ==
:
subs :: [(Term a, Term a)] -> Term a -> Term a
subs subList term = case term of
atom@(Atom x) -> let substitutions =
[ s | s@(Atom x', _) <- subList, x == x' ]
in if null substitutions
then atom
else snd . head $ substitutions
(Compound t1 t2) -> Compound (subs subList t1) (subs subList t2)