为什么以下Haskell脚本无法按预期工作?
find :: Eq a => a -> [(a,b)] -> [b]
find k t = [v | (k,v) <- t]
给定find 'b' [('a',1),('b',2),('c',3),('b',4)]
,解释器返回[1,2,3,4]
而不是[2,4]
。为了实现这一点,下面引入一个名为u
的新变量是必要的:
find :: Eq a => a -> [(a,b)] -> [b]
find k t = [v | (u,v) <- t, k == u]
有谁知道为什么第一个变体没有产生预期的结果?
答案 0 :(得分:14)
像往常一样,列表中的绑定 理解可以影响那些 外部范围;例如:
[ x | x <- x, x <- x ] = [ z | y <- x, z <- y]
另一点:如果您使用-Wall
(或专门针对-fwarn-name-shadowing
)进行编译,则会收到以下警告:
Warning: This binding for `k' shadows the existing binding
bound at Shadowing.hs:4:5
使用-Wall
通常是一个好主意 - 它通常会突出显示在这种可能令人困惑的情况下发生的事情。
答案 1 :(得分:11)
第一个示例中的模式匹配(k,v) <- t
创建了两个新的局部变量v
和k
,这些变量填充了元组t
的内容。模式匹配不会将t
的内容与现有变量k
进行比较,而是创建一个新变量k
(隐藏外部变量)。
通常情况下,模式中不会发生任何“变量替换”,模式中的任何变量名都会创建新的局部变量。
答案 2 :(得分:3)
您只能对文字和构造函数进行模式匹配 您无法匹配变量。 阅读更多here。
话虽如此,您可能对视图模式感兴趣。