如何从函数返回一个整数值而不传递haskell中的任何参数

时间:2014-07-28 15:29:44

标签: haskell

我需要一个函数来读取文件并返回该文件中的行数但不会将任何内容作为参数。我已编写此代码但我收到的错误与IO Int类型不匹配与Int

我从另一个函数调用此函数   让r =行' 帮我解决一下 Thanks`

row'::()->Int

row' ()=do
  content<-readFile "sample.txt"
  let line_file=lines content
  return (length line_file)

1 个答案:

答案 0 :(得分:11)

这里的问题是readFilereturnIO函数,而在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的绑定语法。