Всякий раз, когда у вас возникают такие ошибки типов, как Couldn't match expected type X with actual type Y
, вы должны использовать систему типов haskell, которая поможет вам.
Итак, давайте посмотрим, в чем проблема:
У вас есть чистая функция с типом Int -> Bool
. И вы хотите напечатать отладочный вывод, который явно не чистый (т.е. который находится в монаде IO).
Но в любом случае вы хотите написать s. й. по этим строкам:
foo x
| x > 0 = debug "ok" True
| otherwise = debug "ohhh...no" False
Тем не менее, тип вашей функции должен быть foo :: Int -> Bool
Итак, давайте определим функцию debug
, которая удовлетворит проверку типов. Он должен был бы принять String (ваше отладочное сообщение) и Bool (ваш результат) и оценить только Bool.
debug :: String -> Bool -> Bool
debug = undefined
Но если мы попытаемся реализовать это, это как бы не сработает, поскольку мы не можем избежать монады ввода-вывода, поскольку тип putStrLn — putStrLn :: String -> IO ()
. Чтобы совместить это с оценкой Bool
, нам также придется поместить Bool
в контекст IO
:
debugIO msg result = putStrLn msg >> return result
Хорошо, давайте спросим у ghci тип этой функции:
Main> :t debugIO
debugIO :: String -> b -> IO b
Таким образом, мы получаем IO Bool
, но нам понадобится только Bool
.
Существует ли функция с типом IO b -> b
? Быстрый поиск в hoogle дает нам подсказку:
Печально известный unsafePerformIO :: IO a -> a
имеет нужный нам тип.
Итак, теперь мы могли реализовать нашу функцию debug
в терминах debugIO
:
debug :: String -> Bool -> Bool
debug s r = unsafePerformIO $ debugIO s r
что на самом деле в значительной степени то, что вы получаете с функцией trace
в Debug.Trace
, как уже было указано FUZxxl.
И поскольку мы согласны с тем, что никогда не следует использовать unsafePerformIO
, использование функции trace
предпочтительнее. Просто имейте в виду, что, несмотря на то, что это сигнатура чистого типа, на самом деле она также не ссылочно прозрачна и использует unsafePerformIO
внизу.
person
oliver
schedule
04.10.2011
n
перед тем, как извлечь из него квадратный корень? Это будет работать только для чисел, которые не являются квадратами простых чисел, и не будет работать, например, для 25. - person jwodder   schedule 04.10.2011