Haskell元组与函数参数不匹配

时间:2017-10-07 17:32:47

标签: haskell pattern-matching ghci winghci

我是Haskell的新手,所以这可能是显而易见的,但我做了广泛的Prolog所以我对这个感到困惑......

使用GHCi时,我创建了以下函数(1):

Prelude> let find k t = head [v | (k',v) <- t, k == k'] -- Definiton of find
find :: Eq a1 => a1 -> [(a1, a)] -> a

Prelude> find 2 [(1,11),(2,22)] -- Invocation of find
22

预期。然后我尝试从定义中删除k':

Prelude> let find2 k t = head [v | (k,v) <- t]
find2 :: t -> [(t1, a)] -> a

Prelude> find2 2 [(1,11),(2,22)]
11

我很惊讶地发现价值2实际上与1匹配。 为了确保我不希望不可能,我也尝试以下内容以确认在Haskell中可以进行部分匹配,看起来确实如此:

Prelude> head [v | (2,v) <- [(1,11),(2,22)]]
22

我还注意到函数声明的不同之处。我添加了所需的信息,因此findfind2的声明看起来完全相同。但结果仍然被打破(2,_) matchnig (1,11)

Prelude> let find2 :: Eq a1 => a1 -> [(a1, a)] -> a; find2 k t = head [v | (k,v) <- t]
find2 :: Eq a1 => a1 -> [(a1, a)] -> a

Prelude> find2 2 [(1,11),(2,22)]
11

2如何以任何方式匹配1

(1)上述功能来自优秀的书“Haskell编程”第93页

2 个答案:

答案 0 :(得分:11)

是的,Haskell模式匹配与Prolog模式匹配根本不同。

在Haskell中,模式中的变量引用将由匹配绑定的新变量,而不是必须匹配的现有变量。所以,表达式:

let x = 5 in case (1,2) of (x,y) -> "matched!"   -- gives "matched!"

将始终评估为&#34;匹配!&#34;。这是因为x中的(x,y)刚刚与1绑定,而不是与{{1}的现有&#34;外部定义的值相比较你可以在这里看到:

x

数字常量的行为不同:

let x = 5 in case (1,2) of (x,y) -> x     -- gives "1"

和其他构造函数:

case (1,2) of (5,y) -> "matched!"    -- match fails

不是&#34;重新绑定&#34;但必须匹配模式匹配才能成功。这是字母数字构造函数以大写字母开头的众多原因之一:否则,确定模式是否与现有构造函数匹配或重新绑定到新变量将非常困难。

这适用于任何上下文中的模式匹配,无论是上面的案例表达式还是像这样的函数定义:

case (True,2) of (False,y) -> "match!"   -- match fails

或列出您的例子的理解。在表达式中:

let x = 5
f x = "hi"     -- defines `f` for any `x`, not just `f 5`

变量[v | (k,v) <- [(1,2),(3,4)]] -- gives [(1,2),(3,4)] k将始终是新鲜的,因此将绑定到任何元组尽管 v或{的任何外部现有定义{1}}。如果您使用k(特别是v)启用警告,则会提醒您注意阴影绑定。如果用常量(或其他构造函数)替换-Wall,它的行为会有所不同:

-Wname-shadowing

你可能不喜欢它,但这只是Haskell的工作方式。

答案 1 :(得分:0)

感谢您的帮助!经过一些搜索,我发现这个答案很有用:How can I re-assign a variable in a function in Haskell?

创建一个具有相同名称的新变量,该变量将隐藏前一个变量。但是第一个变量仍然存在,在某些情况下仍然可以访问......

所以这确实远离Prolog,是的,以下标志是非常有用的:

Prelude> :set -fwarn-name-shadowing