我们无法为每种类型read someValue :: someDataType
或show someValue
执行,因为必须在deriving (Show, Read)
声明中写入data
。是否有一个案例,除了错误,我们不希望我们的类型可序列化?
为什么Show与Read分开?是否有一个案例,除了错误,我们只想显示一些数据而不读它?如果没有,为什么不使用单一数据类型Serializable
?
刚才,我正在使用the Key
datatype of the Gloss library导出Show
而不是Read
,这是我不明白的。这很遗憾,因为我想将控件的配置放在一个文件中,然后读取它,这样玩家就可以更改控件并拥有自己的配置。
我不得不为Key,SpecialKey和MouseButton做包装,这不是什么大问题但是没用。
data Key' = Char' Char | SpecialKey' SpecialKey | MouseButton' MouseButton
deriving (Eq, Ord, Show, Read)
convertKey x = case x of
Char' c -> Char c
SpecialKey' sk -> SpecialKey sk
MouseButton' mb -> MouseButton mb
答案 0 :(得分:11)
首先,并非所有数据类型都可以显示,例如无法显示函数,因此不能显示(也不能读取)所有数据类型。最初的Haskell定义指定如果没有给出派生子句,那么将导出尽可能多的派生类。这使得很难知道实际导出了哪些类,因此更改了Haskell定义以强制显式派生子句。
其次,在原始的Haskell定义中,show
和read
函数在Text
类中捆绑在一起。当你导出Show
和Read
时,这不是什么大问题,但是当你手工编写它们时会很痛苦。您经常要定义一个特殊的show
函数,但现在您也被迫编写read
函数,因此最好将它们分开。就个人而言,我几乎总是派生Show
,但几乎从不Read
。
Show
和Read
类并不是真正用于序列化,而是用于简单的输入和输出。
答案 1 :(得分:10)
为什么Show与Read
分开我不知道为什么这是最初的,但是觉得它应该持久,因为可以显示一些(非常少)类型,或者显示占位符字符串,但是不能读回来。函数是典型的例子。
考虑它的另一种方式:将事物放在单独的类中非常容易,但很难在一个类中处理太多的函数,这些函数在相同的上下文中并不总是有意义的。许多人认为Num
类是这个问题的一个主要例子。
我如何read
关键字和其他类型不在Read
第一步:发送一个补丁,将Read
添加到派生实例集。第二步:使用独立派生来解决问题:
{-# LANGUAGE StandaloneDeriving #-}
deriving instance Show Key
第三步:使用CPP使您的代码可以使用任何版本的代码库,无论是具有Ben有朝一日会发布的Read实例的光泽库,还是没有版本的。
为什么没有Serializable
类?
对于初学者来说,有a Serialize class。此外,文本是序列化事物的可怕方式。也许你想要一个更加懒惰的序列化类,在这种情况下你应该看到Binary class。如果你担心表现,那么你可能会喜欢blaze-builder,虽然我老实说从未使用它。
答案 2 :(得分:7)
并非所有类型都可序列化。如何在String -> String
和String
之间建立同构?如果您为Read
提供Show
和String -> String
个实例,我可以找到一个不可序列化的函数:
evil :: String -> String
evil s = map succ (read s s ++ " evil")
假设
read (show evil) = evil
我们得到了
evil (show evil)
= map succ (read (show evil) (show evil) ++ " evil")
= map succ (evil (show evil) ++ " evil")
= map succ (evil (show evil)) ++ "!fwjm"
所以如果定义了evil (show evil)
,那么第一个字符c
就会满足c = succ c
,这是不可能的。
通常,函数无法序列化。有时,我们编写打包函数的数据类型,因此并非每个数据类型都可序列化。如,
data Psychiatrist
= Listen (String -> Psychiatrist)
| Charge Int
有时,即使对于这些类型,您也可以选择提供Read
(有些情况下缺失)和Show
的部分实现(例如,使用占位符或函数列表),但是没有规范的方式来选择它们或理由为什么你会期望两者。
正如其他人所提到的,严重的序列化是Serialize
的保留。我倾向于使用Show
和Read
进行诊断,特别是在ghci中尝试。为此,Show
更有用,因为ghci有一个 Haskell 解析器来进行读取。