3

我们不能为每种类型都做read someValue :: someDataTypeor ,因为必须写在声明中。除了错误之外,是否存在我们不希望我们的类型可序列化的情况?为什么 Show 与 Read 分开?有没有一种情况,除了错误,我们只想显示一些数据而不读取它?如果没有,为什么没有单一的数据类型?show someValuederiving (Show, Read)dataSerializable

刚才,我正在使用Gloss 库Key数据类型,它派生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
4

3 回答 3

11

首先,不是所有的数据类型都可以显示,例如不能显示函数,所以不是所有的数据类型都可以显示(也不能读取)。最初的 Haskell 定义规定,如果没有给出派生子句,那么将派生尽可能多的派生类。这使得很难知道实际派生了哪些类,因此更改了 Haskell 定义以强制显式派生子句。

其次,在最初的 Haskell 定义中,showread函数在Text类中捆绑在一起。Show当您导出and时这不是什么大问题Read,但是当您手动编写它们时会很痛苦。你经常想定义一个特殊的show函数,但现在你不得不写一个read函数,所以最好把它们分开。就我个人而言,我几乎总是派生出Show,但几乎从来没有Read

ShowRead并不是真的用于序列化,而是用于简单的输入和输出。

于 2012-07-04T17:39:14.077 回答
10

为什么显示与阅读分开

我不知道这最初是为什么,但觉得它应该持续存在,因为可以显示一些(很少)类型,或者显示占位符字符串,但不能读回。函数是典型的例子。

另一种思考方式:将事物放在单独的类中很容易,但很难在一个类中处理在相同上下文中并不总是有意义的太多函数。许多人认为Num课堂是这个问题的一个典型例子。

我如何read键入和其他类型不在Read

第一步:发送一个补丁添加Read到派生实例集。第二步:通过使用独立派生来解决:

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

第三步:使用 CPP 使您的代码与任一版本的代码库一起工作,无论是 Ben 将在某一天发布的带有 Read 实例的 Gloss 库,还是没有的版本。

为什么没有Serializable课?

对于初学者,有一个 Serialize 类。此外,文本是序列化事物的一种可怕方式。也许您想要一个更惰性的序列化类,在这种情况下您应该看到Binary 类。如果您关心性能,那么您可能会喜欢blaze-builder,尽管老实说我从未使用过它。

于 2012-07-04T17:29:47.717 回答
7

并非每种类型都是可序列化的。如何在 和 之间建立同String -> StringString?如果你给我ReadShow实例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. 我倾向于使用ShowRead用于诊断目的,尤其是在 ghci 中进行尝试。为此目的,Show它更有用,因为 ghci 有一个Haskell解析器来进行读取。

于 2012-07-04T17:56:00.903 回答