我是haskell的新手,我编写了项目详细信息的代码并搜索每个项目的详细信息。
type Code = Int
type Name = String
type Database = (Code,Name)
textfile::IO()
textfile = appendFile "base.txt" (show[(110,"B")])
搜索代码
fun::IO ()
fun=do putStrLn"Please enter the code of the product"
x<-getLine
let y = read x :: Int
show1 y
textshow::IO [Database]
textshow= do x<-readFile "base.txt"
let y=read x::[Database]
return y
show1::Code->IO ()
show1 cd= do o<-textshow
let d=[(x,y)|(x,y)<-o,cd==x]
putStr(show d)
但是,问题是,它对单个数据有效,如果我追加另一个数据,那么当我尝试搜索该项时它会显示错误Prelude.read: no parse
。
帮助将不胜感激!!
答案 0 :(得分:4)
您的问题是数据文件的格式。使用textfile
后,该文件包含以下内容:
[(110,"B")]
这是一个很好的清单,它有效。第二次使用textfile
后,该文件包含以下内容:
[(110,"B")][(110,"B")]
这不是一个好的清单,它失败了。您可以在ghci
:
*Main> read "[(110,\"B\")][(110,\"B\")]" :: [Database]
*** Exception: Prelude.read: no parse
很明显,read
需要一个列表,而不是两个列表。
如果要附加到包含单个Haskell列表的文件,则需要读取该文件,附加到列表中,并将新列表作为替换文件写入文件中。
addToFileList :: (Read a, Show a) => FilePath -> a -> IO ()
addToFileList fp a = do olds <- readFile fp `catch` \e ->
if isDoesNotExistError e
then return "[]"
else ioError e
let oldl = read olds
newl = oldl ++ [a]
news = show newl
length news `seq`
writeFile fp news
由于有两种情况,这有点棘手:
readFile
是懒惰的,同一文件的writeFile
可能会失败,除非确保已经读取了整个文件。在上面的函数中,这是通过在写入文件之前询问新字符串的长度来解决的(seq
函数确保在写入操作发生之前计算长度。)catch
子句来处理该异常情况。