ben*_*wad 8 parsing haskell file
我有一个格式[(String,String)]的元组列表,我需要一个函数将列表的内容写入文本文件,然后另一个函数将该文本文件作为相同的元组列表读取.这是我的保存功能:
save :: Table -> IO()
save [] = writeFile "database.txt" ""
save zs = do { writeFile "database.txt" "" ; sequence_ [appendFile "database.txt" ("("++a++","++b++")\n") | (a,b) <- zs] }
Run Code Online (Sandbox Code Playgroud)
这是文本文件的好格式吗?那么我怎样才能读取该文本文件并将其转换回元组列表?
eph*_*ent 12
定义于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
Run Code Online (Sandbox Code Playgroud)
简而言之,这些是Haskell中的标准"序列化"方法. show :: (Show a) => a -> String可以将任何实例Show转换为字符串,并将read :: (Read a) => String -> a字符串转换为任何实例Read(或抛出异常).
大多数内置类型和数据结构标准库有Show和Read实例定义; 如果你是从它们组成部分,你的类型也有Show和Read实例定义.
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)
Run Code Online (Sandbox Code Playgroud)
如果Table是数据类型,则必须要求实例,但您可以请求编译器自动为您导出它们.
data Table = Table [(String, String)]
deriving (Read, Show)
Run Code Online (Sandbox Code Playgroud)
有时这是不可能的,你必须定义自己的实例.
instance Show Table where
showsPrec p x = ...
instance Read Table where
readsPrec p x = ...
Run Code Online (Sandbox Code Playgroud)
但这不应该是常见的.
该show/ read方法将正常工作,我用它为好,但仅限于小的值.在更大,更复杂的值read上将非常缓慢.
这个人为的例子证明了以下方面的糟糕表现read:
data RevList a = (RevList a) :< a | Nil
deriving (Show, Read)
ghci> read "(((((((((((((((Nil)))))))))))))))" :: RevList Int
Run Code Online (Sandbox Code Playgroud)
此外,read将无法读取一些有效的Haskell表达式,尤其是那些使用中缀构造函数的表达式(如:<我的示例中所示).其原因read是不知道运营商的固定性.这也是为什么show $ Nil :< 1 :< 2 :< 3会产生许多看似多余的括号.
如果你想为更大的值进行序列化,我建议使用其他一些像Data.Binary这样的库.这将比简单更复杂show,主要是因为缺乏deriving Binary.但是,有各种通用的编程解决方案可以为您提供deriving类似的代理.
结论:我会说,使用show/ read解决方案直到达到极限(可能一旦你开始构建实际应用程序),然后开始寻找更可扩展(但也更复杂)的东西,比如Data.Binary.
旁注:对那些对解析器和更高级的Haskell感兴趣的人; 我给出的例子来自论文:Haskel你读过我吗?,另一种类似快速 read的功能.