Definita in Prelude
,
type ShowS = String -> String
class Show a where
showsPrec :: Int -> a -> ShowS
show :: a -> String
showList :: [a] -> ShowS
type ReadS a = String -> [(a, String)]
class Read a where
readsPrec :: Int -> ReadS a
readList :: ReadS [a]
read :: (Read a) => String -> a
In breve, questi sono i metodi standard "serializzazione" in Haskell. show :: (Show a) => a -> String
può trasformare qualsiasi cosa che sia un'istanza di Show
in una stringa e read :: (Read a) => String -> a
può trasformare una stringa in qualsiasi cosa che sia un'istanza di Read
(o generare un'eccezione).
La maggior parte dei tipi e delle strutture dati incorporati nella libreria standard hanno le istanze Show
e Read
definite; se stai componendo parti da esse, il tuo tipo ha anche le istanze Show
e Read
definite.
type Table = [(String, String)]
load :: (Read a) => FilePath -> IO a
load f = do s <- readFile f
return (read s)
save :: (Show a) => a -> FilePath -> IO()
save x f = writeFile f (show x)
Se Table
erano un tipo di dati, si deve chiedere per le istanze, ma è possibile richiedere che il compilatore li derivare automaticamente per voi.
data Table = Table [(String, String)]
deriving (Read, Show)
A volte questo non è possibile e devi definire le tue istanze.
instance Show Table where
showsPrec p x = ...
instance Read Table where
readsPrec p x = ...
Ma questo non dovrebbe essere comune.
Per derivare Binary, http://repetae.net/computer/haskell/DrIFT/ viene in mente. Detto questo, è certamente possibile leggere e mostrare le istanze di RevList in questo caso semplice, e sono d'accordo che OP dovrebbe rimanere semplice fino a quando la scalabilità non diventa un problema. – ephemient