我在Haskell中有以下代码,它在bookFromFile函数的第一行给出了一个错误。我做错了什么?
错误代码低于下方。
import Data.List
import System.IO
type Book = (Int, String, String, String, String, String, String)
main = do
inputFile <- openFile "catalogo.txt" ReadMode
let b = (bookFromFile inputFile)
print "done"
bookFromFile :: Handle -> Book
bookFromFile inputFile = do
--Read&Store stuff from file
isbn <- fmap read (hGetLine inputFile) :: IO Int
title <- (hGetLine inputFile)
author <- (hGetLine inputFile)
genre <- (hGetLine inputFile)
date <- (hGetLine inputFile)
publisher <- (hGetLine inputFile)
summary <- (readSummary inputFile) --readSummary :: Handle -> IO String (works well)
putStr (summary ++ "\n")
--Construct and return a book
(isbn, title, author, genre, date, publisher, summary)
奇怪的是,(Int,String,String,String,String,String,Int)甚至不是我为书定义的类型。 错误消息:
* Couldn't match type `IO'
with `(,,,,,,) Int String String String String String'
Expected type: (Int, String, String, String, String, String, Int)
Actual type: IO Int
* In a stmt of a 'do' block:
isbn <- fmap read (hGetLine inputFile) :: IO Int
In the expression:
do { isbn <- fmap read (hGetLine inputFile) :: IO Int;
putStr ((show isbn) ++ "\n");
title <- (hGetLine inputFile);
putStr (title ++ "\n");
.... }
答案 0 :(得分:3)
有三个小问题:
bookFromFile
需要坐在IO
中 - 您可以看到这一点,因为您使用hGetLine
和putStr
b <- bookFromFile...
而不是let b = bookFromFile ...
return
元组你也可以摆脱许多(...)
这样的
main = do
inputFile <- openFile "catalogo.txt" ReadMode
b <- bookFromFile inputFile
print "done"
bookFromFile :: Handle -> IO Book
bookFromFile inputFile = do
--Read&Store stuff from file
isbn <- fmap read (hGetLine inputFile)
title <- hGetLine inputFile
author <- hGetLine inputFile
genre <- hGetLine inputFile
date <- hGetLine inputFile
publisher <- hGetLine inputFile
summary <- readSummary inputFile --readSummary :: Handle -> IO String (works well)
putStr (summary ++ "\n")
--Construct and return a book
return (isbn, title, author, genre, date, publisher, summary)
答案 1 :(得分:2)
bookFromFile
的类型签名必须是Handle->IO Book
,因为此函数使用IO。
此外,由于该功能在IO中,因此您不应使用let b = ....
来调用它,而是使用b <- ....
。
您还需要在函数的最后一行使用return
来实际将值包装在返回所需的IO中。
答案 2 :(得分:1)
bookFromFile
应该尽可能地使思维尽可能纯净,所以可能是这样的:
import Data.List
import System.IO
type Book = (Int, String, String, String, String, String, String)
bookFromStrings:: [String] -> Maybe Book
bookFromStrings [isbn,title,author,genre,date,publisher,summary] =
Just (read isbn,title,author,genre,date,publisher,summary)
bookFromStrings _ = Nothing
bookFromString :: String -> Maybe Book
bookFromString str = bookFromStrings (begin ++ [unlines rest]) where
(begin, rest) = splitAt 6 (lines str)
bookFromHandle :: Handle -> IO (Maybe Book)
bookFromHandle h = do
str <- hGetContents h
return (bookFromString str)
bookFromFile :: FilePath -> IO (Maybe Book)
bookFromFile file = withFile file ReadMode bookFromHandle
如果您为Book
data Book = Book {isbn :: Int, title :: String ...}