Haskell中的变量

时间:2010-10-29 16:15:18

标签: variables haskell

为什么以下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]

有谁知道为什么第一个变体没有产生预期的结果?

3 个答案:

答案 0 :(得分:14)

来自Haskell 98 Report

  

像往常一样,列表中的绑定   理解可以影响那些   外部范围;例如:

     

[ 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创建了两个新的局部变量vk,这些变量填充了元组t的内容。模式匹配不会将t的内容与现有变量k进行比较,而是创建一个新变量k(隐藏外部变量)。

通常情况下,模式中不会发生任何“变量替换”,模式中的任何变量名都会创建新的局部变量。

答案 2 :(得分:3)

您只能对文字和构造函数进行模式匹配 您无法匹配变量。 阅读更多here

话虽如此,您可能对视图模式感兴趣。