我需要一个函数来读取文件并返回该文件中的行数但不会将任何内容作为参数。我已编写此代码但我收到的错误与IO Int
类型不匹配与Int
。
我从另一个函数调用此函数 让r =行' 帮我解决一下 Thanks`
row'::()->Int
row' ()=do
content<-readFile "sample.txt"
let line_file=lines content
return (length line_file)
答案 0 :(得分:11)
这里的问题是readFile
和return
是IO
函数,而在Haskell中执行IO
的任何函数都必须在其类型中表示这一点。您可以改为将函数编写为
row' :: IO Int
row' = do
content <- readFile "sample.txt"
let line_file = lines content
return (length line_file)
这会编译得很好。类型签名中的这种限制是为了确保任何具有副作用或可以为同一输入返回不同值的函数被类型系统划分。这可以极大地帮助推理您的代码,因为对于纯函数,例如
countRows :: String -> Int
countRows content = length (lines content)
始终可以保证为同一输入返回相同的结果。然后你就可以使用这些&#34; pure&#34;功能&#34; impure&#34;用于执行实际计算的功能,保持所有不纯的&#34;包含在一个地方的副作用:
row'' :: IO Int
row'' = do
content <- readFile "sample.txt"
return (countRows content)
现在row''
除了读取文件外没有做任何事情,并将内容传递给实际执行计算该文件中行的工作的函数。您甚至可以使用fmap
作为
row'' :: IO Int
row'' = fmap countRows $ readFile "sample.txt"
要使用此功能,您可以执行类似
的操作main :: IO ()
main = do
putStrLn "Counting the number of rows in sample.txt"
r <- row''
putStrLn $ "There are " ++ show r ++ " row(s) in sample.txt"
但请注意,row''
必须从另一个IO
函数调用,无法将其用作
-- THIS IS WRONG, WON'T COMPILE
doubleRows :: Int
doubleRows = rows'' * 2
-- THIS IS WRONG TOO
doubleRows' :: Int
doubleRows' = do
r <- rows''
return (r * 2)
因为这两个示例都必须使用IO Int
类型,而第一个示例即使使用正确的类型签名也不会编译,因为IO Int * Int
不能生成任何类型感觉,你必须先提取&#34;提取&#34;来自Int
的{{1}}使用IO Int
的绑定语法。