我目前正在研究haskell的董事会评估员。我正在尝试使用带有多个参数的函数的map;我已经阅读了有关此问题的其他SO问题但仍然遇到类型错误,所以也许我只是误解了Haskell类型(我是一个Python程序员)。无论哪种方式,这是代码:
scorePiecesRow [] _ = 0
scorePiecesRow (x:xs) y
| x == y = 1 + (scorePiecesRow xs y)
| x == '-' = 0 + (scorePiecesRow xs y)
| otherwise = -1 + (scorePiecesRow xs y)
scorePieces [] _ = 0
scorePieces board y = foldr (+) 0 (map (scorePiecesRow y) board)
scorePiecesRow
在我传递"wwwb--" 'w'
(返回3
)之类的内容时效果很好,但只要我调用scorePieces
(例如scorePieces ["www", "bb-"] 'w'
哪个应该返回1
),我得到一堆类型错误:
<interactive>:37:14: Couldn't match expected type `Char' with actual type `[Char]' In the expression: "www" In the first argument of `scorePieces', namely `["www", "bb-"]' In the expression: scorePieces ["www", "bb-"] 'w' <interactive>:37:21: Couldn't match expected type `Char' with actual type `[Char]' In the expression: "bb-" In the first argument of `scorePieces', namely `["www", "bb-"]' In the expression: scorePieces ["www", "bb-"] 'w' <interactive>:37:28: Couldn't match expected type `[Char]' with actual type `Char' In the second argument of `scorePieces', namely 'w' In the expression: scorePieces ["www", "bb-"] 'w' In an equation for `it': it = scorePieces ["www", "bb-"] 'w'
我对错误消息感到有点困惑。例如,第一个告诉我,它期待Char
,但scorePiecesRow
的第一个参数需要[Char]
。
如果有人能够对此有所了解,我们将不胜感激!
答案 0 :(得分:4)
虽然Haskell会为你推断类型,但它们通常也非常有价值,可以写出你的代码(以机器检查方式!)并检查你的假设。我们可以在这里完成Haskell类型推理引擎的工作,以弄清楚我们对这些函数的了解。
由于scorePiecesRow
已添加到1 + (scorePiecesRow xs y)
中的数字,我们知道结果必须位于类型Num
中(其中(+)
已定义)
scorePiecesRow :: Num a => ... -> a
此外,通过查看参数中的模式匹配,我们可以很容易地看到第一个参数必须是列表。
scorePiecesRow :: Num a => [b] -> ... -> a
因为我们使用(==)
将第一个参数的元素与第二个参数进行比较,所以我们知道它们必须是类型相同的类型Eq
(其中(==)
已定义! )。
scorePiecesRow :: (Num a, Eq b) => [b] -> b -> a
最后,将第一个参数的元素与'-'
的相等性进行比较,因此我们知道它们实际上必须是Char
。由于String
是[Char]
的同义词,我们可以将其归咎于此。
scorePiecesRow :: (Num a) => String -> Char -> a
我们可以对scorePieces
做同样的事情来了解
scorePieces :: Num a => String -> String -> a
这是我们看到问题的地方。您正在呼叫scorePieces ["www", "bb-"] 'w'
,即[String]
和Char
,而scorePieces
则需要String
和另一个String
。
错误告诉了你这一点,但是由于String
和[Char]
相同而且有点混乱,GHC在报告错误时往往会将类型简化为最简单的形式。
答案 1 :(得分:1)
由于scorePiecesRow
将[Char]
和Char
作为参数,因此,当您在地图函数中调用scorePiecesRow y
时,Haskell会决定y
必须是[Char]
类型,因为它是scorePiecesRow
的第一个参数。
这是第三条错误消息的来源,因为Haskell期待[Char]
,但你给它Char
。
前两个基本上是相同的,因为scorePiecesRow y
期望Char
,因此,当您将此函数映射到board
时,Haskell期望board
具有类型[Char]
,因此当您为其提供[[Char]]
类型的板时它会失败。
也许尝试以下方法:
scorePiecesRow _ [] = 0
scorePiecesRow y (x:xs)
| x == y = 1 + (scorePiecesRow y xs)
| x == '-' = 0 + (scorePiecesRow y xs)
| otherwise = -1 + (scorePiecesRow y xs)
scorePieces [] _ = 0
scorePieces board y = foldr (+) 0 (map (scorePiecesRow y) board)
或者,如果您想保持scorePiecesRow
功能相同,
scorePieces [] _ = 0
scorePieces board y = foldr (+) 0 (map (\row -> scorePiecesRow row y) board)