2013-11-08 2 views
2

В настоящее время я работаю над оценщиком доски в haskell. Я пытаюсь использовать карту с функцией с несколькими параметрами; Я прочитал другие вопросы SO, касающиеся этого, но продолжаю получать ошибки типа, поэтому, возможно, я просто недопонимаю типы Haskell (я программист на Python). В любом случае, вот код:Карта Haskell с несколькими параметрами и проблемами типа

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]. Если бы кто-нибудь мог пролить свет на это, было бы очень полезно!

ответ

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 имеет тенденцию уменьшать типы до их простейшей формы при сообщении об ошибках.

+0

А ... это имеет большой смысл! Спасибо, что потратили время на то, чтобы пройти через это так тщательно - эта штука совпадения скоро будет привыкать :) – mondayRain

1

Поскольку scorePiecesRow принимает в качестве аргументов [Char] и Char, когда в вашей функции карты, вы звоните scorePiecesRow y, Haskell решает, что y должен быть типа [Char], как это дано в качестве первого аргумента scorePiecesRow.

Это источник третьего сообщения об ошибке, так как Haskell ожидает [Char], но вы даете ему Char.

Первые два, по существу, то же самое, что scorePiecesRow y ожидает Char и так, когда карта этой функции над board, Haskell ожидает board иметь тип [Char], и, таким образом, он терпит неудачу, когда вы даете ему совет type [[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) 
Смежные вопросы