Haskell - двойная личность IO/ST монада?
У меня есть код, который в настоящее время использует 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", когда вы действительно хотите запустить он.
Ответы
Ответ 1
Если вам нужен унифицированный интерфейс IORef
и STRef
, просмотрели ли вы пакет stateref
? Он имеет классы типов для "ссылок на изменяемые данные", разделенных для чтения, записи и т.д. С экземплярами для IORef
и STRef
, а также такими вещами, как TVar
, MVar
, ForeignPtr
и т.д..
Ответ 2
Вы считали вместо Debug.Trace.trace?
http://www.haskell.org/haskellwiki/Debugging