【问题标题】:Haskell -- dual personality IO / ST monad?Haskell——双重人格IO / ST monad?
【发布时间】:2011-10-13 19:40:32
【问题描述】:

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

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

编辑/解决方案

非常感谢 [第 n 次],C.A.麦肯!使用该解决方案,我能够为支持 pdebug 函数的 monad 引入一个附加类。 ST monad 将忽略这些调用,而 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”的东西调用它它。

【问题讨论】:

    标签: haskell monads io-monad st-monad


    【解决方案1】:

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

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

    【讨论】:

    • 我目前正在使用它。但是,它也有其弱点,例如跟踪结果只打印一次:在变量有值之后(例如 ST 计算的结果),它不会被重新计算。示例:我在 ghci 中输入seq (somecomp somedata) ();第一次打印调试和错误消息,第二次只是错误。当然,:r 可以工作,但我希望它有更好的语义 [即Debug.Trace 有点像 hack]。
    【解决方案2】:

    如果你想要IORef 和STRef 的统一接口,你看过the stateref package 吗?它具有“对可变数据的引用”的类型类,为可读、可写等而分隔,具有IORef 和STRef 的实例,以及TVar、MVar、ForeignPtr 等的实例.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-15
      • 2022-01-22
      • 2016-08-12
      • 2019-01-23
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多