Haskell——双重性格 IO/ST monad?

发布于 2024-11-26 09:22:48 字数 953 浏览 2 评论 0原文

我有一些代码当前使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゝ杯具 2024-12-03 09:22:48

如果您想要 IORefSTRef 的统一接口,您是否查看过 stateref?它具有“对可变数据的引用”的类型类,分为可读、可写等,并具有 IORefSTRef 的实例,以及 TVarMVarForeignPtr 等。

If you want a unified interface to IORef and STRef, have you looked at the stateref package? It has type classes for "references to mutable data", separated for readable, writable, etc., with instances for IORef and STRef, as well as things like TVar, MVar, ForeignPtr, etc.

っ左 2024-12-03 09:22:48

您是否考虑过使用 Debug.Trace.trace 来代替?

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

Have you considered Debug.Trace.trace instead?

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文