Haskell中出现意外的模式匹配

时间:2014-09-15 10:13:23

标签: haskell pattern-matching

在WinGHCI中加载以下示例后,我尝试评估

father p1
father p2
father p3

所有三个表达式都产生相同的值:

Person "John" "Huston"

怎么可能?

如果我取消注释最后一行,我会收到以下警告:

test.hs:14:1: Warning:
Pattern match(es) are overlapped
In an equation for ‘father’: father p2 = ...

发生了什么?


data Person = Person String String deriving (Show)

p1 :: Person
p1 = Person "Charlie" "Chapling"

p2 :: Person
p2 = Person "John" "Huston" 

p3 :: Person
p3 = Person "Frank" "Sinatra"

father :: Person -> Person

father p1 = p2

--father p2 = p3

3 个答案:

答案 0 :(得分:3)

你误解了

的含义
father p1 = p2

本节中的变量p1未引用您之前定义的p1。相反,它是一个新变量,该子句匹配任何参数值。

您可以使用GHC 7.8' pattern synonyms来做您正在尝试的事情:

pattern P1 = Person "Charlie" "Chaplin"

p2 :: Person
p2 = Person "John" "Huston" 

p3 :: Person
p3 = Person "Frank" "Sinatra"

father :: Person -> Person
father P1 = p2
father _ = undefined

代码未经测试,因为我没有安装GHC 7.8。

答案 1 :(得分:1)

问题是你的函数中的p1与所有内容相匹配(你也可以写x - 它没有任何区别。)

我认为你想要做的是:

data Person = Person String String deriving (Show, Eq)

-- ... rest of your code - p1, p2, ...

father :: Person -> Person
father p
   | p == p1 = p2
   | p == p2 = p3
   | otherwise = undefined -- what do you want to do here?

我建议不要使用这样的函数,只是重新定义Person以包含这些信息:

data Person = Person { givenName :: String, surName :: String, father :: Maybe Person }
   deriving (Show, Eq)

答案 2 :(得分:0)

p1定义中的father变量与全局p1没有任何关系。模式匹配总是引入新变量,从不使用全局变量。所以,你的定义等同于:

father aaa = p2
--father bbb = p3

你可以使用这样的守卫:

father p | p == p1 = p2
         | p == p2 = p3

我还建议总是使用编译器选项-Wall。您可能会看到一些有趣的警告。事实上,他们至少会指出你正确的方向,所以你可能不需要问SO。