У меня есть код, который в настоящее время использует монаду ST для оценки. Мне нравится не помещать ввод-вывод везде, потому что метод runST
дает чистый результат и указывает на то, что такой результат можно безопасно вызывать (по сравнению с unsafePerformIO
). Однако, поскольку часть моего кода стала длиннее, я действительно хочу для включения отладочных операторов печати.
Существует ли какой-либо класс, который предоставляет монаду с двумя личностями [или механизм классов типов], который может быть ST или IO (в зависимости от его типа или флага "isDebug")? напомним, SPJ представил класс «Mutation» в своей статье «Fun with Type Functions», в которой использовались ассоциативные типы для связи IO с IORef и ST с STRef. Существует ли где-нибудь такой класс в виде пакета?
Спасибо очень много [в энный раз], CA 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. Поскольку он ожидает, что выражения будут типами ввода-вывода по умолчанию, запуск чего-то вроде "test 3" приведет к запуску монады ввода-вывода, поэтому вы можете легко отладить ее, а затем вызвать ее с чем-то вроде "testR", когда вы действительно хотите запустить это.