如何将用户输入与元组列表相结合,并将完整的元组列表写入文件?

时间:2011-10-04 11:08:48

标签: haskell

我正在尝试接受用户输入并以元组列表的形式转换它。 我想要做的是,我需要从用户那里获取数据并以形式转换它 [(Code,Name, Price)]并最终将此用户输入与前一个列表组合在一起,并将新列表写入同一文件。

我面临的问题是,一旦程序完成用户输入,WinHugs就会显示错误,如Program error: Prelude.read: no parse

以下是代码:

type Code=Int
type Price=Int
type Name=String
type ProductDatabase=(Code,Name,Price)

finaliser=do
           a<-input_taker 
           b<-list_returner
           let w=a++b
           outh <- openFile "testx.txt" WriteMode
           Print outh w
           Close outh   

2 个答案:

答案 0 :(得分:0)

问题是,当您同时写入文件时,您正在使用惰性IO来读取文件。当read看到已部分写入的数据时,这会导致问题。

在尝试写入文件之前,我们需要强制读取输入数据。一种方法是使用seq强制将产品列表读入内存。

list_returner :: IO ([ProductDatabase])
list_returner = do
    inh <- openFile "testx.txt" ReadMode
    product_text <- hGetContents inh
    let product :: [ProductDatabase]
        product = read product_text
    product `seq` hClose inh
    return product

此外,如果文件为空,则会失败。在第一次运行代码之前,该文件应至少包含[],以便它将作为空列表进行解析。

答案 1 :(得分:0)

代码看起来很好,除了某些样式点。它应该像那样工作。尝试更多地分开关注点。 “无解析”异常意味着read函数无法将其参数字符串转换为所需类型。 Hugs附带的基础库可能对空格和换行更具限制性。我建议一般使用GHC而不是Hugs。

如果您感兴趣:您可能需要考虑的一个样式点是使用withFile而不是openFile / hClose组合。您可能还想将writeFileshow

一起使用
writeFile "testx.txt" (show w)

另一个样式点:您的input_taker操作不应返回列表。没有理由返回列表。返回单个元组,因此您可以使用(:)代替(++)。一般来说,(++)的使用表明您可能采取了错误的方法。

此外,您的ProductDatabase类型名称具有误导性,因为我会将[ProductDatabase]解释为数据库列表。你的元组是Product

最终的风格点:这真的只是代码美,所以它是有争议的。这不是C / C ++,所以你真的想写f x而不是f(x)

    ...
    return product

-- Since your `Product` is just a type alias, I would use
-- a smart constructor:
product :: Code -> Name -> Price -> Product
product = (,,)

readProduct :: IO Product
readProduct = do
    ...
    code <- fmap read getLine
    ...
    name <- getLine
    ...
    price <- fmap read getLine
    return (product code name price)