1

我在Show为自定义数据类型定义实例时遇到问题。

data Circle = Circle { x::Float, y::Float, r::Float }

instance Show Circle where 
show :: Circle -> String
show circle = concat $ 
  intersperse "," (map Prelude.show [x circle, y circle, r circle])

这一切都存在于一个名为Main.Calling Main.show circfor some Circle的模块中,circ导致堆栈溢出异常。为什么甚至Prelude.show被 GHC 解释为对我在这里定义的函数的调用?

4

2 回答 2

7

这是一个缩进问题。这是更正:

data Circle = Circle { x::Float, y::Float, r::Float }

instance Show Circle where 
  -- Illegal syntax
  -- show :: Circle -> String
  show circle = concat $ 
    intersperse "," (map show [x circle, y circle, r circle])

当您忘记缩进时,您会得到两个单独的声明:

instance Show Circle where { }

还有一个功能:

show :: Circle -> String

让我们忽略这个函数,因为它永远不会被调用。当您定义一个空类实例时,您将获得函数的默认定义。这将通过 Haskell 类型检查器,因为show默认为 using showsPrec,并且showsPrec默认为 using show。如果您覆盖这两种方法中的一种或两种,您将获得Show. 如果您都没有覆盖,默认实现将相互递归并溢出堆栈。

关于Prelude.show

上面的代码中只有一个show,那就是Prelude.show. 当你实现一个类时,你并没有实现一个名为“show”的函数,而是为泛型函数提供了一个新的实现Prelude.show

于 2013-09-24T03:14:43.963 回答
0

我们还可以使用InstanceSigs扩展在实例内使用签名。不要忘记在“ where”中使用空格。

{-# LANGUAGE InstanceSigs #-}
data Circle = Circle { x::Float, y::Float, r::Float }

instance Show Circle where 
    show :: Circle -> String
    show circle = concat $ 
        intersperse "," (map show [x circle, y circle, r circle])
于 2013-09-24T08:48:05.953 回答