我有一个包含IOREF作为重要元素的数据类型。这意味着没有一种干净的方法使其成为成员 show 类型类。这还不错,因为我有 print 在IO MONAD中的功能。但这在GHCI中很烦人,因为每次我返回这些东西时,我都会出现一个错误,说明它无法显示。

是否有一种方法可以在IO Monad中使用IO动作来显示结果?如果没有,写作会产生任何负面影响 show a = unsafePerformIO $ print a?

有帮助吗?

解决方案

您是否考虑过将.ghci文件添加到类似的文件中:

instance (Show a) => Show (IORef a) where
    show a = show (unsafePerformIO (readIORef a))

这根本不是安全的,但是如果这仅仅是为了您的个人使用,也许可以。

对于更通用的使用,以前给出的答案对我来说看起来不错。也就是说,要么定义静态“我不能显示此消息”消息:

instance Show (IORef a) where
    show _ = "<ioref>"

这将给出类似的东西:

> runFunc
MyStruct <ioref> 4 "string val"

或使用自定义功能。我建议上课并举起所有演出实例:

class ShowIO a where
    showIO :: a -> IO String

instance Show a => ShowIO a where
    showIO = return . show
instance ShowIO a => ShowIO (IORef a) where
    showIO a = readIORef a >>= showIO

给出输出(未经测试,这只是手写):

> myFunc >>= showIO
MyStruct "My String in an IORef" 4 "string val"

其他提示

GHCI有三个用于返回值的情况:

  1. Show a => a: :只需运行表演并打印
  2. Show a => IO a: :执行动作,运行显示和打印
  3. IO (): :什么都没有打印

因此,通常,如果您键入IO操作,则执行它,并且结果如果不是 (). 。让我们尝试一下:

ghci>15
15
ghci>'a' : 'b' : 'c' : []
"abc"
ghci>putStrLn "Hello, world!"
Hello, world!
ghci>putStrLn "Hello, world!" >> return 42
Hello, world!
42
ghci>

如果要打印不同的东西,最好的方法可能是编写自定义功能并将其粘在您想要看到的每一行的前面:

myShowFun :: ... -> IO String

ghci> myShowFun $ ...
foobar
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top