Этот код Haskell содержит ошибку типа, тупую ошибку с моей стороны, которая будет очевидна после ее просмотра.
Я понял, но это было сложно. Мой вопрос: Как я должен был диагностировать это?
class Cell c where
start :: c
moves :: c -> [c]
score :: Cell c => (c -> Float) -> Int -> c -> Float
score estimate limit x =
foldr (scoreRed (limit - 1)) (-1) (moves x)
where
scoreRed limit x best =
max best $ foldr (scoreBlue limit best x) 1 (moves x)
scoreBlue limit best x worst =
if limit <= 0
then estimate x
else min worst $ foldr (scoreRed (limit - 1)) best (moves x)
main = return ()
Примечания:
- Все, что называется
limit
, имеет типInt
. - Все имена с именем
x
имеют типc
, экземплярCell
. -
best
иworst
-Float
. -
score
,estimate
,scoreRed
иscoreBlue
все возвращаютсяFloat
. - Я удалил кучу кода, чтобы упростить его для этого вопроса. Сосредоточьтесь на типах, а не на рабочем времени.
Сообщение об ошибке из GHC 7.6.3:
[1 of 1] Compiling Main ( Game.hs, Game.o )
Game.hs:13:12:
Couldn't match expected type `c -> c' with actual type `Float'
In the return type of a call of `estimate'
Probable cause: `estimate' is applied to too many arguments
In the expression: estimate x
In the expression:
if limit <= 0 then
estimate x
else
min worst $ foldr (scoreRed (limit - 1)) best (moves x)
Почему я нашел это трудно:
-
Фактическая ошибка не указана в строке 13 и не имеет ничего общего с
estimate
. -
Казалось, что ошибка может быть вызвана почти любым идентификатором в программе.
-
Иногда добавление явных объявлений типов ко всему помогает, но не здесь: я не знаю, как писать объявления типа для
scoreRed
иscoreBlue
. Если я напишуscoreRed :: Int -> Float -> c -> Float
тогда GHC думает, что я вводил новую переменную типа
c
, не ссылаясь на переменную типаc
вscore
. Я получаю разные сообщения об ошибках, но не лучшие.
Похоже, что "пожалуйста, дай мне рыбу" версия этого вопроса была задана десятками раз. Как насчет того, что мы научим меня ловить рыбу. Я готов.