写入文件的好习惯
Good practice to write to a file
在我的程序的主要功能中,我调用了 timesRule,它是一个布尔值 return。在这个函数中,我想写入一个文件。但是,如果我理解正确的话,函数时间规则在写入文件时需要 return IO() 。
我应该如何构建代码以在函数中写入文件 returning 布尔值?
timesRule :: (MultiSet LocalType) -> Bool
timesRule sequent = do
let result = MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
let file = "tmp/log.txt"
let content = "TIMES rule: " ++ (show(MultiSet.toList result))
let log = writeToFile file content
prefixRule result
使用的函数:
import qualified System.IO.Strict as SIO
writeToFile :: FilePath -> String -> IO()
writeToFile file content = do
x <- SIO.readFile file
writeFile file ("\n"++content)
appendFile file x
正如@Robin Zigmond 指出的那样,比较明显的解决方案是将您的函数类型更改为 IO Bool
。
不过,除了调用 writeToFile
之外,您的语法还有一些问题。为了使您的函数 timesRule
具有给定的类型,它需要如下所示:
timesRule :: (MultiSet LocalType) -> Bool
timesRule sequent = -- there is no do here
let
result = MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
-- the following two lines are superfluous ...
file = "tmp/log.txt"
content = "TIMES rule: " ++ (show(MultiSet.toList result))
-- ... because this still doesn't work
log = writeToFile file content
-- ... and what were you going to use `log` for, anyway?
in
prefixRule result
将您的类型更改为 IO Bool
允许您使用 monadic do 语法。 Bool
本身既没有应用实例也没有 monad 实例,因此没有有意义的 do 语法。 (为了拥有一个应用程序或一个 monad 实例,您需要一个类型函数,如 Maybe
或 IO
,仅供参考):
timesRule :: (MultiSet LocalType) -> IO Bool
timesRule sequent = do
let
result = MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
file = "tmp/log.txt"
content = "TIMES rule: " ++ (show(MultiSet.toList result))
-- the syntax to get the value of type `a` out of `IO a` is this:
log <- writeToFile file content
-- the function to turn a value of type `a` into `IO a` is `pure`:
pure (prefixRule result)
您仍然不使用 log
,不妨更换
log <- writeToFile file content
与
writeToFile file content
鉴于 writeToFile
具有类型 ... -> IO ()
,() 发音为“unit”,log 的值为 ()
因此 log
不包含任何有用的信息(可能)。
不太明显的解决方案是稍微重构您的代码并分离关注点。有时将函数写入文件 and return 一些布尔值确实有意义。在你的情况下,你可能想要一个 returns result
的函数,即将这一行变成一个函数:
MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
然后你已经有 prefixRule
给你 Bool
并且你有 writeFile
。通过这种方式,您可以将纯代码(任何不具有类型 IO something
的代码)与具有 IO 副作用的代码分开。
在我的程序的主要功能中,我调用了 timesRule,它是一个布尔值 return。在这个函数中,我想写入一个文件。但是,如果我理解正确的话,函数时间规则在写入文件时需要 return IO() 。 我应该如何构建代码以在函数中写入文件 returning 布尔值?
timesRule :: (MultiSet LocalType) -> Bool
timesRule sequent = do
let result = MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
let file = "tmp/log.txt"
let content = "TIMES rule: " ++ (show(MultiSet.toList result))
let log = writeToFile file content
prefixRule result
使用的函数:
import qualified System.IO.Strict as SIO
writeToFile :: FilePath -> String -> IO()
writeToFile file content = do
x <- SIO.readFile file
writeFile file ("\n"++content)
appendFile file x
正如@Robin Zigmond 指出的那样,比较明显的解决方案是将您的函数类型更改为 IO Bool
。
不过,除了调用 writeToFile
之外,您的语法还有一些问题。为了使您的函数 timesRule
具有给定的类型,它需要如下所示:
timesRule :: (MultiSet LocalType) -> Bool
timesRule sequent = -- there is no do here
let
result = MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
-- the following two lines are superfluous ...
file = "tmp/log.txt"
content = "TIMES rule: " ++ (show(MultiSet.toList result))
-- ... because this still doesn't work
log = writeToFile file content
-- ... and what were you going to use `log` for, anyway?
in
prefixRule result
将您的类型更改为 IO Bool
允许您使用 monadic do 语法。 Bool
本身既没有应用实例也没有 monad 实例,因此没有有意义的 do 语法。 (为了拥有一个应用程序或一个 monad 实例,您需要一个类型函数,如 Maybe
或 IO
,仅供参考):
timesRule :: (MultiSet LocalType) -> IO Bool
timesRule sequent = do
let
result = MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
file = "tmp/log.txt"
content = "TIMES rule: " ++ (show(MultiSet.toList result))
-- the syntax to get the value of type `a` out of `IO a` is this:
log <- writeToFile file content
-- the function to turn a value of type `a` into `IO a` is `pure`:
pure (prefixRule result)
您仍然不使用 log
,不妨更换
log <- writeToFile file content
与
writeToFile file content
鉴于 writeToFile
具有类型 ... -> IO ()
,() 发音为“unit”,log 的值为 ()
因此 log
不包含任何有用的信息(可能)。
不太明显的解决方案是稍微重构您的代码并分离关注点。有时将函数写入文件 and return 一些布尔值确实有意义。在你的情况下,你可能想要一个 returns result
的函数,即将这一行变成一个函数:
MultiSet.concatMap (\x -> if isPrl x then [checkTimes x, checkTimes2 x] else [x] ) sequent
然后你已经有 prefixRule
给你 Bool
并且你有 writeFile
。通过这种方式,您可以将纯代码(任何不具有类型 IO something
的代码)与具有 IO 副作用的代码分开。