我正在尝试创建一个程序,为目录(及其子目录)中的每个文件添加一个简单的文本标题。我需要使用ghc中的内置函数(我无法访问cabal)来执行此操作。
函数的类型签名是
odd 99795
even 42462
这些都可以独立工作,但由于类型的原因,我很难结合使用这两个函数。我假设使用地图将是正确的方法,但到目前为止,我没有成功。
getRecursiveContents :: FilePath -> IO [FilePath]
addHeaderToFile :: String -> FilePath -> IO ()
据我所知,由于所使用的类型,这不起作用,但我找不到解决方法。
答案 0 :(得分:4)
首先运行生成文件列表的IO操作:
addHeaderToMultiple :: String -> IO [FilePath] -> IO ()
addHeaderToMultiple header files = do
-- files has type IO [FilePath]
paths <- files
-- paths has type [FilePath], so we can map over that
map (addHeaderToFile header) paths
-- this produces [IO ()], which is not IO ()
我们在最后一行遇到了一个问题,它构建了IO操作列表而不是运行它们。我们可以使用辅助函数:
runInSequence :: [IO ()] -> IO ()
runInSequence [] = return () -- nothing to do
runInSequence (a:as) = a >> runInSequence as
可以简化为
runInSequence = foldr (>>) (return ())
实际上,已经存在一个库函数:它被称为sequence_
。我们的代码现在变为
import Control.Monad
addHeaderToMultiple header files = do
paths <- files
sequence_ (map (addHeaderToFile header) paths)
-- this produces IO (), so it's OK
组合sequence_ (map ...
也有自己的库函数,名为mapM_
:
addHeaderToMultiple header files = do
paths <- files
mapM_ (addHeaderToFile header) paths
可以使用>>=
直接进一步细化
addHeaderToMultiple header files =
files >>= mapM_ (addHeaderToFile header)