First of all, show
is expected to produce a string following the Haskell syntax -- ideally, one should be able to cut & paste that into a Haskell file and have that work.
That being said, read . show
is expected to be the identity. However, sometimes it is relaxed a bit, only requiring that
read (show x) == x
where (==)
is the equivalence defined by the related Eq
instance.
I believe the archetypal example for this is Data.Set.Set
, which internally represents sets using balanced binary search trees (BST). Its Show
instance produces strings of the form
fromList [1,2,3,4,6,7]
read
ing back such a string likely produces a different BST, but one which is still ==
to the old one. From the user's point of view, there's no (observable) difference.
When printing a custom "opaque" type the same fromSomeTransparentType value
string encoding can often be used.
Finally, I guess these Show
-related "social contracts" are much more respected in libraries than in applications. This is because in applications one sometimes can reasonably assume that no one else - but the application itself - will ever use these instances. E.g., I think this is okay-ish for an application:
data Exp = Add Exp Exp | ...
instance Show Exp where
show (Add e1 e2) = "(" ++ show e1 ++ ", " ++ show e2 ++ ")"
The "other" law show . read == id
does not hold, in general. First, read
is partial. Second, even disregarding partiality, the read
method is allowed to be more lenient on its input, e.g. treating repeated whitespace as a single one, or neglecting redundant parentheses: (as AJFarmar suggests below)
show (read "Just (((6)))") = "Just 6"