18

我有一些代码目前使用 ST monad 进行评估。我不喜欢将 IO 放在任何地方,因为该runST方法会产生纯结果,并表明这样的结果可以安全调用(相对于unsafePerformIO)。但是,由于我的一些代码变得更长,我确实想将调试打印语句放入其中。

是否有任何类提供双重人格 monad [或 typeclass 机器],可以是 ST 或 IO(取决于其类型或“isDebug”标志)?我记得 SPJ 在他的“Fun with Type Functions”论文中引入了一个“Mutation”类,它使用关联类型将 IO 与 IORef 和 ST 与 STRef 相关联。这样的东西在某处作为一个包存在吗?

编辑/解决方案

非常感谢 [第 n 次],CA McCann!pdebug使用该解决方案,我能够为支持函数的 monad 引入一个附加类。monad将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 中有一个非常幸运的结果。由于默认情况下它期望表达式是 IO 类型,运行类似“test 3”的东西会导致 IO monad 被运行,所以你可以很容易地调试它,然后当你真正想要运行时用类似“testR”的东西调用它它。

4

2 回答 2

17

如果你想要一个统一的接口IORefSTRef你看过吗?它具有用于“对可变数据的引用”的类型类,为可读、可写等而分隔,具有 和 的实例,以及诸如、、等的实例。staterefIORefSTRefTVarMVarForeignPtr

于 2011-07-26T22:50:42.013 回答
10

您是否考虑过 Debug.Trace.trace ?

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

于 2011-07-26T22:29:48.497 回答