当我手动编写PhisicalCell数据类型的简单show实例时,程序会占用所有空间。在派生他自己的Show版本时,这不会发生。为什么呢?
这是我正在编写的代码的简化版本:
import Data.Array
type Dimensions = (Int, Int)
type Position = (Int, Int)
data PipeType = Vertical | Horizontal | UpLeft | UpRight | DownLeft | DownRight deriving (Show)
data PhisicalCell = AirCell
| PipeCell PipeType
| DeathCell
| RecipientCell Object
-- deriving (Show) SEE THE PROBLEM BELOW
data Object = Pipe { pipeType :: PipeType -- tipo di tubo
, position :: Position -- posizione del tubo
, movable :: Bool -- se posso muoverlo
}
| Bowl { position :: Position -- posizione dell'angolo in alto a sinistra
, dimensions :: Dimensions -- dimensioni (orizzontale, verticale)
, waterMax :: Int -- quanta acqua puo' contenere al massimo
, waterStart :: Int -- con quanta acqua parte
, hatch :: Maybe Position -- un eventuale casella di sbocco
, sourceIn :: [Position] -- posti da cui l'acqua entra
, movable :: Bool -- se posso muoverlo
}
| Death
deriving (Show)
data Level = Level Dimensions [Object]
type LevelTable = Array Dimensions PhisicalCell
-- HERE IS THE PROBLEM --
instance Show PhisicalCell where
show AirCell = " "
show (PipeCell _) = "P"
show DeathCell = "X"
show (RecipientCell _) = "U"
both :: (a -> b) -> (a,a) -> (b,b)
both f (a,b) = (f a, f b)
levelTable :: Level -> LevelTable
levelTable (Level dim _) = initial
where initial = array ((0,0), both (+1) dim) $
[((x,y), AirCell) | x <- [1..fst dim], y <- [1..snd dim] ]
++ [((x,y), DeathCell) | x <- [0..fst dim + 1], y <- [0, snd dim + 1]]
++ [((x,y), DeathCell) | x <- [0, fst dim + 1], y <- [0..snd dim + 1]]
main = print $ levelTable (Level (8,12) [])
答案 0 :(得分:7)
The Show
type class has mutually referencing default implementations:
class Show a where
-- | Convert a value to a readable 'String'.
--
-- 'showsPrec' should satisfy the law
-- ...
...
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
因此,如果您声明Show
实例而未定义任何方法
instance Show where
nextNewFunction :: Bla
...
GHC将很乐意编译所有默认值,因此不会有任何错误。但是,只要你尝试使用中的任何一个,你就会像你的Objects
一样陷入一个致命的循环......并且相互递归最终会使堆栈崩溃。
现在,你的代码看起来并不像你有一个空的instance Show
声明,但实际上你做了:因为错误的缩进,你定义的show
被识别为一个新的免费顶级函数,它恰好与GHC.Show.show
具有相同的名称。你可以添加
show :: PhisicalCell -> String
到您的文件并获得与现在相同的结果。
答案 1 :(得分:3)
问题实际上在于Sassa NF指出的间距。当我缩进节目时,它可以工作(当我没有时,我得到堆栈溢出)。如果没有缩进,您将定义从未使用过的顶级show
函数,而show
Show
实例的PhisicalCell
函数具有未定义的show
函数1}}函数,导致问题。