У меня есть код, который в настоящее время использует ST-монаду для оценки. Мне нравится не помещать IO повсюду, потому что метод runST
создает чистый результат и указывает, что такой результат безопасен для вызова (по сравнению с unsafePerformIO
). Однако, поскольку некоторые из моих кодов получили больше, я хочу, чтобы вывести отладочные заявления печати.
Существует ли какой-либо класс, который предоставляет монаду с двумя личностью [или машиной для машинного оборудования], которая может быть ST или IO (в зависимости от ее типа или флага isDebug)? Я помню, SPJ представила класс "Мутация" в своей статье "Развлечения с типом функций", в которой использовались ассоциативные типы для привязки IO к IORef и ST к STRef. Существует ли такое как пакет где-то?
Редактировать/решить
Большое спасибо [nth time], C.A. McCann! Используя это решение, я смог ввести дополнительный класс для монад, поддерживающих функцию pdebug
. Монада ST
будет игнорировать эти вызовы, тогда как IO
будет запускать putStrLn
.
class DebugMonad m where
pdebug :: String -> m ()
instance DebugMonad (ST s) where
pdebug _ = return ()
instance DebugMonad IO where
pdebug = putStrLn
test initV = do
v <- newRef initV
modifyRef v (+1)
pdebug "debug"
readRef v
testR v = runST $ test v
Это очень удачное последствие в ghci. Поскольку ожидается, что выражения будут типами ввода-вывода по умолчанию, запуск чего-то типа "тест 3" приведет к тому, что будет выполняться монада IO, чтобы вы могли легко отлаживать его, а затем называть его чем-то вроде "testR", когда вы действительно хотите запустить он.