Haskell - 双重人格IO / ST monad? [英] Haskell -- dual personality IO / ST monad?

查看:153
本文介绍了Haskell - 双重人格IO / ST monad?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些目前使用ST monad进行评估的代码。因为 runST 方法产生一个纯粹的结果,所以我不喜欢把IO放在任何地方,并且表明这样的结果可以安全调用(与 unsafePerformIO )。然而,因为我的一些代码已经变得更长了,所以我想把调试打印语句放进去。



是否有任何类提供双重个性monad [或类型类机械],可以是ST或IO(取决于其类型或isDebug标志)?我记得SPJ在他的Fun with Type Functions一文中介绍了一个Mutation类,该类使用关联类型将IO与IORef和ST关联到STRef。这样做是否在某个地方存在?



编辑/解决方案



非常感谢(第n次) CA麦肯!使用该解决方案,我可以为monad引入一个额外的类,它支持 pdebug 函数。 ST monad将忽略这些调用,而 IO 将运行 putStrLn

  class DebugMonad m其中
pdebug :: String - > m()

实例DebugMonad(ST s)其中
pdebug _ = return()

实例DebugMonad IO其中
pdebug = putStrLn

test initV = do
v< - newRef initV
modifyRef v(+1)
pdebugdebug
readRef v
testR v = runST $ test v

这在ghci中有非常幸运的结果。由于默认情况下表达式是IO类型,因此运行类似test 3的操作会导致IO monad运行,因此您可以轻松进行调试,然后在实际运行时使用类似testR的方式调用它如果你想要一个统一的接口< IORef 和 code> STRef ,你看过 stateref ?它具有用于可变数据引用的类型类,以可读,可写等形式分隔,并且实例为 IORef STRef ,以及诸如 TVar MVar ForeignPtr 等。


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.

解决方案

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.

这篇关于Haskell - 双重人格IO / ST monad?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆