Reputation: 1523
We can't do read someValue :: someDataType
or show someValue
for every type because deriving (Show, Read)
has to be written in the data
declarations. Is there a case, other than mistake, where we don't want our type to be serializable?
Why is Show separated from Read? Is there a case, other than mistake, we only want to show some data and not read it? If not, why not have a single data type Serializable
?
Just now, I'm using the Key
datatype of the Gloss library which derives Show
and not Read
, which I don't understand. It's a shame because I wanted to put the configuration of the controls in a file and then read it, so the player can change the controls and have his own configuration.
I had to do wrappers for Key, SpecialKey and MouseButton, which is not a big deal but is useless.
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
Upvotes: 3
Views: 2074
Reputation: 43383
Not every type is serializable. How can you establish an isomorphism between String -> String
and String
? If you give me Read
and Show
instances for String -> String
, I can find a function which isn't serialisable like this:
evil :: String -> String
evil s = map succ (read s s ++ " evil")
Suppose
read (show evil) = evil
We get
evil (show evil)
= map succ (read (show evil) (show evil) ++ " evil")
= map succ (evil (show evil) ++ " evil")
= map succ (evil (show evil)) ++ "!fwjm"
so if evil (show evil)
is defined, then it has a first character c
satisfying c = succ c
, which is impossible.
In general, functions can't be serialized. Sometimes, we write datatypes which pack up functions, so not every datatype is serializable either. E.g.,
data Psychiatrist
= Listen (String -> Psychiatrist)
| Charge Int
Sometimes, even for these types, you might choose to provide partial implementations of Read
(with some cases missing) and Show
(e.g., with placeholders for or tabulations of functions), but there is no canonical way to choose them or reason why you would expect both.
As others have mentioned, serious serialization is the preserve of Serialize
. I tend to use Show
and Read
for diagnostic purposes, especially trying things out in ghci. For that purpose, Show
is by far more useful, because ghci has a Haskell parser to do the reading.
Upvotes: 7
Reputation: 23014
First, not all data types can be shown, for instance functions cannot be shown, so not all data types can be shown (nor read). The original Haskell definition specified that if no deriving clause was given then as many derived classes as is possible would be derived. This made it difficult to know what classes were actually derived, so the Haskell definition was changed to force explicit deriving clauses.
Second, in the original Haskell definition the show
and read
functions where bundled together in the Text
class. This isn't much of a problem when you derive Show
and Read
, but it is a pain when you write them by hand. You often want to define a special show
function, but now you are forced to write a read
function as well, so it's better to keep them separate. Personally I almost always derive Show
, but almost never Read
.
The Show
and Read
classes are not really meant to be used for serialization, but rather for simple input and output.
Upvotes: 11
Reputation: 64740
Why is Show separate from Read
I don't know why this was originally, but feel it should persist because some (very few) types can be shown, or have a placeholder string shown, but not read back in. Functions are the typical example.
Another way to think about it: It's very easy to place things in separate classes but very hard to deal with too many functions in one class that doesn't always make sense in the same contexts. Many people feel the Num
class is a prime example of this issue.
How Can I read
Key and other types not in Read
Step one: send in a patch adding Read
to the set of derived instances. Step two: make a work around by using standalone deriving:
{-# LANGUAGE StandaloneDeriving #-}
deriving instance Show Key
Step three: Use CPP to make your code work with either version of the codebase, be it the Gloss library with a Read instances that Ben will someday release or the version without.
Why isn't there a Serializable
class?
For starters, there is a Serialize class. Also, text is a horrible way to serialize things. Perhaps you'd want a lazier serialize class in which case you should see the Binary class. If you're concerned about performance then you might like blaze-builder, though I've honestly never used it.
Upvotes: 10