开发者

How to combine user input with list of tuples and write the complete list of tuples to the file?

I am trying to take user input and convert it in the form of a list of tuples. What I want to do is that, I need to take the data from the user and convert it in the form of [(Code,Name, Price)] and finally combine this user input with the previous list and write the new list to the same file.

The problem I am facing is that as soon as the program completes taking 开发者_高级运维user input, WinHugs is showing an error like this Program error: Prelude.read: no parse.

Here is the code:

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   


The problem is that you're using lazy IO to read from a file while you're writing to it at the same time. This causes problems when read sees data that has been partially written.

We need to force the reading of the input data to be complete before you try writing to the file. One way of doing this is to use seq to force the list of products to be read into memory.

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

Also, this will fail if the file is empty. The file should contain at least [] before running your code the first time, so that it will parse as the empty list.


The code looks fine to me, except for certain style points. It should work like that. Try to separate concerns more. The exception "no parse" means that the read function was unable to convert its argument string to the desired type. The base library coming with Hugs may be more restrictive on spaces and line feeds. I would recommend using GHC instead of Hugs in general.

In case you're interested: One style point you may want to consider is using withFile instead of an openFile/hClose combination. You may also want to use the writeFile with show:

writeFile "testx.txt" (show w)

Another style point: Your input_taker action should not return a list. There is really no reason to return a list. Return a single tuple instead, so you can use (:) instead of (++). In general the usage of (++) indicates that you may be taking the wrong approach.

Further your ProductDatabase type name is misleading, because I would interpret [ProductDatabase] as a list of databases. Your tuple is a Product.

Final style point: This is really just about code beauty, so it's controversial. This is not C/C++, so you would really want to write f x instead of 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)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜