具有多个参数和类型问题的Haskell映射

时间:2013-11-08 01:37:04

标签: haskell map

我目前正在研究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]。 如果有人能够对此有所了解,我们将不胜感激!

2 个答案:

答案 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)