【发布时间】:2014-06-24 16:53:30
【问题描述】:
我正在尝试扩展常规降价,使其能够引用其他文件,以便引用文件中的内容呈现在“主”文件中的相应位置。
但我来的最远的是实施
createF :: FTree -> IO String
createF Null = return ""
createF (Node f children) = ifNExists f (_id f)
(do childStrings <- mapM createF children
withFile (_path f) ReadMode $ \handle ->
do fc <- lines <$> hGetContents handle
return $ merge fc childStrings)
ifNExists 只是一个可以忽略的助手,真正的问题发生在读取句柄时,它只是返回空字符串,我认为这是由于惰性 IO 造成的。
我认为使用withFile filepath ReadMode $ \handle -> {-do stutff-}hGetContents handle 是正确的解决方案,因为我读过fcontent <- withFile filepath ReadMode hGetContents 是个坏主意。
另一个让我困惑的是函数
createFT :: File -> IO FTree
createFT f = ifNExists f Null
(withFile (_path f) ReadMode $ \handle ->
do let thisParse = fparse (_id f :_parents f)
children <-rights . map ( thisParse . trim) . lines <$> hGetContents handle
c <- mapM createFT children
return $ Node f c)
像魅力一样工作。
那么为什么createF 只返回一个空字符串?
整个项目和要测试的目录/文件可以在github找到
这里是数据类型定义
type ID = String
data File = File {_id :: ID, _path :: FilePath, _parents :: [ID]}
deriving (Show)
data FTree = Null
| Node { _file :: File
, _children :: [FTree]} deriving (Show)
【问题讨论】:
-
如果您打开文件只是为了执行
getContents,那么您最好执行fmap myPureFunction (readFile filename),这样所有这些都会消失。readFile将在读取文件内容后关闭文件。