为什么这个 Haskell 中的 Show 实例(拥抱)会导致堆栈溢出错误



以下是Haskell中的多态数据类型,由Hugs解释。我正在尝试创建一个"平等显示"的实例。

实例声明指出,如果类型"a"在"显示"中,则相等 a 在"显示"中。它应该将两个参数打印到构造函数 Equals a b,形式为"a = b"。

data Equality a = Equals a a 
instance (Show a) => Show (Equality a) where
show (Equals a b) = a ++ " = " ++ b

然而,在拥抱中输入诸如"(平等 9 9("之类的内容会产生:

错误 - C 堆栈溢出

所以,我尝试缩进"显示(等于 b(..."与几个空格一起行。我不确定会有什么区别,但只是在玩,然后得到了这个:

Inferred type is not general enough
*** Expression    : show
*** Expected type : Show (Equality a) => Equality a -> String
*** Inferred type : Show (Equality [Char]) => Equality [Char] -> String

谁能解释为什么会发生这些错误,或者建议实现此 show 实例的更好方法?

谢谢!

您的代码缩进不正确。它定义了一个空的Show实例:

instance (Show a) => Show (Equality a) where

以及一个单独的顶级函数show

show (Equals a b) = a ++ " = " ++ b

类型 Equality [Char] -> [Char] .因此,当您尝试使用 Show 实例时,将选取 Show 类中 show 的默认定义。查看代码:

showsPrec _ x s = show x ++ s
show x          = showsPrec zeroInt x ""

您可以看到默认show是根据showsPrec定义的,而又是根据show定义的。这就解释了为什么你的程序会进入无限循环。

若要修复代码,请适当地缩进它,并向show添加缺少的调用以修复类型错误(该错误源于您无法将任意类型a与字符串连接的事实 - 您必须先将a转换为字符串(:

data Equality a = Equals a a
instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

测试:

*Main> show (Equals 9 9)
"9 = 9"
由于

Haskell 有时奇怪的空格敏感性,缩进确实很重要。如果没有缩进,编译器无法分辨以下语句属于where

您得到的错误是因为多态类型没有约束,不能确保ab可以与" = "字符串连接。如果你有Equals 1 1怎么办.如果不先制作 Ints 字符串,您将如何连接它?

但是,如果您先show a 和 b,则一切都会成功,因为show将值分解为可以与字符串连接的内容。

data Equality a = Equals a a
instance (Show a) => Show (Equality a) where
    show (Equals a b) = (show a) ++ " = " ++ (show b)

我认为您的问题是您没有在参数ab上调用函数show。我在 GHC 中这样做了,但我认为它应该有效:

data Equality a = Equals a a 
instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

然后:

> Equals 9 9
9 = 9

相关内容

最新更新