为什么这个 Haskell 代码会产生堆栈溢出?
Why does this Haskell code produce a 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
谁能解释这种行为?
您没有定义实例的方法。 show
的默认值使用 showPrec
(通过 shows
),showPrec
的默认值使用 show
。所以你有一个循环定义,它最终显然会溢出堆栈。也许您打算派生一个实例?
Prelude> data ImNewToHaskell = AndWhatIsThis deriving (Show)
Prelude> show AndWhatIsThis
"AndWhatIsThis"
编辑:解决 instance
和 deriving
的所有问题:
当您键入 instance
时,表示 "I am going to define my own instance or leverage the type class's default code":
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
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
我是第一次玩 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
谁能解释这种行为?
您没有定义实例的方法。 show
的默认值使用 showPrec
(通过 shows
),showPrec
的默认值使用 show
。所以你有一个循环定义,它最终显然会溢出堆栈。也许您打算派生一个实例?
Prelude> data ImNewToHaskell = AndWhatIsThis deriving (Show)
Prelude> show AndWhatIsThis
"AndWhatIsThis"
编辑:解决 instance
和 deriving
的所有问题:
当您键入 instance
时,表示 "I am going to define my own instance or leverage the type class's default code":
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
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