我需要它读取文件并返回该文件的行数一个功能,但作为一个argument.I写了这个代码,但我得到的是不可能匹配类型的错误也不会采取任何IO Int有Int.
我从另一个函数调用此函数,因为让r = row'帮助我弄清楚谢谢`
row'::()->Int
row' ()=do
content<-readFile "sample.txt"
let line_file=lines content
return (length line_file)
Run Code Online (Sandbox Code Playgroud)
bhe*_*ilr 11
这里的问题是readFile并且return是IO函数,并且IO在Haskell 中执行的任何函数都必须在其类型中表示这一点.你可以把你的函数写成
row' :: IO Int
row' = do
content <- readFile "sample.txt"
let line_file = lines content
return (length line_file)
Run Code Online (Sandbox Code Playgroud)
这会编译得很好.类型签名中的这种限制是为了确保任何具有副作用或可以为同一输入返回不同值的函数被类型系统划分.这可以极大地帮助推理您的代码,因为对于纯函数,例如
countRows :: String -> Int
countRows content = length (lines content)
Run Code Online (Sandbox Code Playgroud)
始终可以保证为相同的输入返回相同的结果.然后你可以在"不纯"函数中使用这些"纯"函数来执行实际计算,将所有"不纯"副作用保存在一个位置:
row'' :: IO Int
row'' = do
content <- readFile "sample.txt"
return (countRows content)
Run Code Online (Sandbox Code Playgroud)
row''除了读取文件并将内容传递给实际执行计算该文件中的行的工作的函数之外,现在不执行任何操作.您甚至可以使用fmapas 更简单地说明这一点
row'' :: IO Int
row'' = fmap countRows $ readFile "sample.txt"
Run Code Online (Sandbox Code Playgroud)
要使用此功能,您可以执行类似的操作
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"
Run Code Online (Sandbox Code Playgroud)
但请注意,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)
Run Code Online (Sandbox Code Playgroud)
因为这两个例子就必须有类型IO Int代替,因为第一个甚至不会用正确的类型签名编译IO Int * Int没有任何意义,你必须先"提取"的Int从IO Int使用的绑定语法r <-.