为什么GHC类型检查器不像两个看起来几乎相同的函数之一?

时间:2016-08-26 13:19:35

标签: haskell

我正在尝试解决Haskell Book中第11章“代数数据类型”中的章节练习之一。但是我遇到了一个类型错误,无法理解为什么一个非常相似的函数有效,而另一个则没有。

这就是我的开始:

type Digit = Char

type Presses = Int

data DaPhone =
  DaPhone [(Char, Digit, Presses)]
  deriving Show

myPhone :: DaPhone
myPhone =
  DaPhone [('a', '2', 1), ('b', '2', 2), ('c', '2', 3)]

reverseTaps :: DaPhone -> Char -> [(Digit, Presses)]
reverseTaps aPhone aChar = foldr f [] aPhone
  where f (c, d, p)
          | c == aChar = ((d, p):)
        f _         = id

并收到以下错误:

daPhone.hs:29:39: Couldn't match expected type ‘t0 (Char, Digit, Presses)’ …
                with actual type ‘DaPhone’
    In the third argument of ‘foldr’, namely ‘aPhone’
    In the expression: foldr f [] aPhone
Compilation failed.

但是如果我尝试使用几乎相同类型的几乎相同的函数,例如:

myList :: [(Char, Char, Int)]
myList = [('a', '2', 1), ('b', '2', 2), ('c', '2', 3)]

myFunction :: [(Char, Char, Int)] -> Char -> [(Char, Int)]
myFunction aList aChar = foldr f [] aList
  where f (c, d, p)
          | c == aChar = ((d,p):)
        f _           = id

它按预期编译和工作:

λ> myFunction myList 'a'
[('2',1)]
λ> myFunction myList 'b'
[('2',2)]
λ> myFunction myList 'c'
[('2',3)]

那么,为什么我在reverseTaps中出现类型错误,这与myFunction非常相似? (我想这是关于DaPhone的定义,意思是我可能需要在foldr等中进行更多的模式修补,但我找不到具体的方法。)

1 个答案:

答案 0 :(得分:3)

在我看来,你只需要

myFunction (DaPhone aList) aChar = ...

DaPhone解包为实际的列表