为什么这个Haskell代码会产生堆栈溢出?

时间:2015-03-14 22:16:14

标签: haskell stack-overflow

我第一次玩Haskell。我写了这三行,期望得到编译器错误,但在ghci中键入它会导致堆栈溢出。

$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> data ImNewToHaskell = AndWhatIsThis
Prelude> instance Show ImNewToHaskell
Prelude> show AndWhatIsThis
"*** Exception: stack overflow

任何人都可以解释这种行为吗?

2 个答案:

答案 0 :(得分:9)

您没有定义实例的方法。 show的默认设置使用showPrec(通过shows),showPrec的默认值使用show。所以你有一个循环定义,最终会明显溢出堆栈。也许你打算派生一个实例?

Prelude> data ImNewToHaskell = AndWhatIsThis deriving (Show)
Prelude> show AndWhatIsThis
"AndWhatIsThis"

编辑:通过instancederiving清除任何问题:

键入instance表示“我将定义自己的实例或利用类型类的默认代码”:

instance Show Foo where
    show Foo = "This is the string representing Foo"

在数据声明后键入deriving时,编译器会自动为您的类型生成合理的实例:

data MyType = OneOrMoreConstructors deriving (Show)

如果您或其他程序员没有派生出所需的实例而您不想编写自己的实例,那么您可以使用独立派生,这会产生与使用deriving相同的结果,但可能在其自己的行上在另一个模块中:

{-# LANGUAGE StandaloneDeriving #-}
deriving instance Show MyType

答案 1 :(得分:5)

Newer GHC's在那里发出警告:

λ> data ImNewToHaskell = AndWhatIsThis
λ> instance Show ImNewToHaskell

<interactive>:108:10: Warning:
    No explicit implementation for
      either ‘showsPrec’ or ‘show’
    In the instance declaration for ‘Show ImNewToHaskell’
λ> show AndWhatIsThis
"*** Exception: stack overflow

如您所见,您没有为必要的方法定义实现,并且方法的default implementations会导致无限递归,从而导致堆栈溢出。

class  Show a  where
    showsPrec :: Int -> a -> ShowS
    show      :: a   -> String
    showList  :: [a] -> ShowS

    showsPrec _ x s = show x ++ s
    show x          = shows x ""
    showList ls   s = showList__ shows ls s

shows           :: (Show a) => a -> ShowS
shows           =  showsPrec 0