您好,有人可以向我解释一下,如果您知道从那时起要使用它,那么如何将动作的结果存储在let block
中(您需要像标题一样的结果)?
在我的情况下,我两次调用listDirectory
,我想将第一次调用的值保存在变量initialList
中,以便稍后将其长度与以后调用的listDirectory
进行比较。
如何将listDirectory
的第一次调用存储在变量initialList
中?
module Main where
import System.IO
import System.Directory
import DB(db)
import Company
main::IO()
main = do
putStrLn "Insert folder for output:"
folder<-getLine
makeDir folder>>= \b ->
putStrLn (if b then "Created" else "Existed Already")
makeDir::String->IO Bool
makeDir dirname=let root="D:\\"
enumerateDirs=listDirectory root
initialList=<<enumerateDirs in //how can i store it here?
if dirname `elem` initialList then
putStrLn "Directory found , folder count:"++length initialList
else
createDirectory root++dirname>>
length enumerateDirs >initialList
答案 0 :(得分:8)
对IO操作使用绑定而不是let
/ =
。像这样:
makeDir dirname = do
let root = "D:\\"
initialList <- listDirectory root
if dirname `elem` initialList then
putStrLn ("Directory found, folder count: " ++ length initialList)
else createDirectory (root ++ dirname)
finalList <- listDirectory root
return (length finalList > length initialList)
但是,这种用于创建目录的技术存在一些问题。因为您可能不是唯一正在运行的程序:
listDirectory
和createDirectory
之间创建了目录,导致您尝试重新创建一个已经存在的目录并引发异常。listDirectory
和第二个listDirectory
之间创建另一个文件,即使您尚未创建目录,也会导致返回True
新目录。listDirectory
和第二个listDirectory
之间的另一个文件也可能被删除,即使您创建了新目录,也会导致您返回False
。另外,因为dirname
来自未经过滤的用户输入:
dirname `elem` initialList
检查将在错误的目录列表中查找错误的目录名称。例如,如果用户输入a\b
,则当该代码应在目录列表中寻找a\b
时,此代码将在目录列表中搜索D:\
。 b
。对于这种输入,D:\a
比较的逻辑同样是不正确的。要解决这些问题,我建议直接调用length
(即事先没有检查),并使用异常捕获机制来确定它是否失败以及是否由于目录已经存在或调用现有的{ {1}}。