Haskell - монада двойного индивидуального ввода / вывода? - PullRequest
18 голосов
/ 27 июля 2011

У меня есть код, который в настоящее время использует монаду ST для оценки.Мне нравится не помещать IO везде, потому что метод 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», когда вы действительно хотите запуститьэто.

Ответы [ 2 ]

17 голосов
/ 27 июля 2011

Если вам нужен унифицированный интерфейс для IORef и STRef, рассматривали ли вы пакет stateref ? Он имеет классы типов для «ссылок на изменяемые данные», разделенных для читаемых, записываемых и т. Д., С экземплярами для IORef и STRef, а также такими вещами, как TVar, MVar, ForeignPtr и т. Д. .

10 голосов
/ 27 июля 2011

Вы рассматривали Debug.Trace.trace вместо этого?

http://www.haskell.org/haskellwiki/Debugging

...