Первое, что нужно при исследовании ошибок типов, - это записать сигнатуры типов функций, которые вы знаете.
Здесь, решение может иметь тип
solve :: String -> String -> String -> [String] -> String
или
solve :: String -> String -> String -> [String] -> IO String
В зависимости от того, должен ли он иметь побочные эффекты при вычислении значения.Видя, что вы используете mapM
и return
повсюду, я думаю, что версия IO
, возможно, была предназначена.
Теперь, если вы записываете подпись, вы начинаете получать гораздо более значимые сообщения об ошибках.,Например, вместо этого:
tmp.hs:19:16:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: [Char]
Actual type: [[Char]]
In the return type of a call of `solve'
In the first argument of `return', namely
`(solve (prefix ++ header ++ " ") "" sent dict)'
, что не имеет особого смысла, вы получите следующее:
tmp.hs:14:8:
Couldn't match expected type `IO String' with actual type `[a0]'
In the expression: return prefix ++ header
In the expression:
if (header `elem` dict) then return prefix ++ header else return ""
In an equation for `solve':
solve prefix header [] dict
= if (header `elem` dict) then
return prefix ++ header
else
return ""
, которое точно показывает, где проблема.Приложение-функция имеет самый высокий приоритет в Haskell, поэтому return prefix ++ header
эквивалентно (return prefix) ++ header
, что, безусловно, не то, что вы имели в виду.
Кстати, если я удаляю IO
из возвращаемого типа, удалитевсе return
s и изменить вызов, добавив putStrLn
, код компилируется и работает!Единственная проблема заключается в том, что он объединяет все возможные предложения в одну строку без каких-либо разделителей.