Haskell——双重性格 IO/ST monad?
我有一些代码当前使用 ST monad 进行评估。我不喜欢到处都放置 IO,因为 runST
方法会产生纯结果,并表明这样的结果可以安全调用(与 unsafePerformIO
相比)。然而,由于我的一些代码变得更长,我确实想放入调试打印语句。
是否有任何类提供双重人格 monad [或类型类机器],可以是 ST 或 IO (取决于它的类型或“isDebug”标志)?我记得 SPJ 在他的“Fun with Type Functions”论文中介绍了一个“Mutation”类,该类使用关联类型将 IO 与 IORef 以及 ST 与 STRef 相关联。这样的东西是否作为一个包存在于某处?
编辑/解决方案
非常感谢[第n次],CA McCann!使用该解决方案,我能够为支持 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”之类的内容调用它它。
I have some code that currently uses a ST monad for evaluation. I like not putting IO everywhere because the runST
method produces a pure result, and indicates that such result is safe to call (versus unsafePerformIO
). However, as some of my code has gotten longer, I do want to put debugging print statements in.
Is there any class that provides a dual-personality monad [or typeclass machinery], one which can be a ST or an IO (depending on its type or a "isDebug" flag)? I recall SPJ introduced a "Mutation" class in his "Fun with Type Functions" paper, which used associative types to relate IO to IORef and ST to STRef. Does such exist as a package somewhere?
Edit / solution
Thanks very much [the nth time], C.A. McCann! Using that solution, I was able to introduce an additional class for monads which support a pdebug
function. The ST
monad will ignore these calls, whereas IO
will run 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
This has a very fortunate consequence in ghci. Since it expects expressions to be IO types by default, running something like "test 3" will result in the IO monad being run, so you can debug it easily, and then call it with something like "testR" when you actually want to run it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您想要
IORef
和STRef
的统一接口,您是否查看过stateref
包?它具有“对可变数据的引用”的类型类,分为可读、可写等,并具有IORef
和STRef
的实例,以及TVar
、MVar
、ForeignPtr
等。If you want a unified interface to
IORef
andSTRef
, have you looked at thestateref
package? It has type classes for "references to mutable data", separated for readable, writable, etc., with instances forIORef
andSTRef
, as well as things likeTVar
,MVar
,ForeignPtr
, etc.您是否考虑过使用 Debug.Trace.trace 来代替?
http://www.haskell.org/haskellwiki/Debugging
Have you considered Debug.Trace.trace instead?
http://www.haskell.org/haskellwiki/Debugging