Haskell:有任何debugShow函数吗?

4
我想使用 Debug.Trace.trace 来打印我知道是 Show 的内容。就像我在 Python 等语言中所做的那样。
一种解决方法是在我想要放置跟踪的函数的签名中添加 "Show a =>",并在调用它的任何函数中添加该参数等。
但如果我可以使用一些 debugShow 函数来调用 show 如果该值存在,则返回 "--no show--" 或类似的东西,那将会更好。
这是我定义一个 DebugShow 的失败尝试(GHC 拒绝了 "重复实例声明"):
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}

class DebugShow a where
  debugShow :: a -> String

instance Show a => DebugShow a where
  debugShow = show

instance DebugShow a where
  debugShow = const "--no show--"

某种“不安全转换”也可以解决我的问题。

有什么建议吗?

注意-这仅用于调试目的。我不会在任何完成的代码中使用此功能。

4个回答

4
也许你想要以下变体之一:
traceShow :: (Show a) => a -> b -> b
traceShow = trace . show

定义在Debug.Trace中

“如果值有show,则调用show,否则返回“--no show--”或其他内容”的约束条件非常严格。我认为你需要使用重叠(和不一致的)实例来为所有类型定义默认的Show(可能通过unsafeCoerce或通过vacuum实现)。


@dons:当你说通过真空时,你是指什么?这意味着它不能完成吗? - yairchu
3
@yairchu 我的意思是 vacuum:http://hackage.haskell.org/packages/archive/vacuum/0.0.95/doc/html/GHC-Vacuum.html#v%3Avacuum,它可以呈现堆对象(即不需要 Show 字典)。 - Don Stewart

3

我不完全确定,但我认为在不为调用链中的每个调用点添加类上下文的情况下,这是不可能的。原因是:至少在GHC中,每个类都是由一个字典实现的。因此,在使用处,如果存在aShow字典,我们需要它。但要获得它,我们需要它从确定a的地方传递下来,这需要在所有中间函数的签名中有一些东西。


1
“不安全转换”通常被称为unsafeCoerce。请注意其文档中的警告;这是导致崩溃和其他不良行为的简单方法。

1
@ephemient: 谢谢。在这种情况下,似乎我可以使用'unsafeCoerce'将其“转换”为特定类型,但我想将其“转换”为相同的未知类型并将Show添加到其上下文中。我尝试定义"debugShow = show . unsafeCoerce",但这会失败,因为存在“模棱两可的类型变量”。 - yairchu

1

在DebugShow类中使用默认的方法实现即可。这样做应该正好符合您的要求:

{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE UndecidableInstances #-}

class DebugShow a where
  debugShow :: a -> String
  debugShow = const "--no show--"

instance Show a => DebugShow a where
  debugShow = show

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接