Haskell - монада IO / ST с двойной индивидуальностью?

У меня есть код, который в настоящее время использует монаду ST для оценки. Мне нравится не помещать ввод-вывод везде, потому что метод runST дает чистый результат и указывает на то, что такой результат можно безопасно вызывать (по сравнению с unsafePerformIO ). Однако, поскольку часть моего кода стала длиннее, я действительно хочу для включения отладочных операторов печати. ​​

Существует ли какой-либо класс, который предоставляет монаду с двумя личностями [или механизм классов типов], который может быть ST или IO (в зависимости от его типа или флага "isDebug")? напомним, SPJ представил класс «Mutation» в своей статье «Fun with Type Functions», в которой использовались ассоциативные типы для связи IO с IORef и ST с STRef. Существует ли где-нибудь такой класс в виде пакета?

Edit / solution

Спасибо очень много [в энный раз], 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", когда вы действительно хотите запустить это.

18
задан Robin Green 20 May 2018 в 13:39
поделиться