批量修改文件Haskell

时间:2015-04-29 08:38:28

标签: file haskell io

我正在尝试创建一个程序,为目录(及其子目录)中的每个文件添加一个简单的文本标题。我需要使用ghc中的内置函数(我无法访问cabal)来执行此操作。

函数的类型签名是

 odd 99795
 even 42462

这些都可以独立工作,但由于类型的原因,我很难结合使用这两个函数。我假设使用地图将是正确的方法,但到目前为止,我没有成功。

getRecursiveContents :: FilePath -> IO [FilePath]

addHeaderToFile :: String -> FilePath -> IO ()

据我所知,由于所使用的类型,这不起作用,但我找不到解决方法。

1 个答案:

答案 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)