批量修改文件Haskell
Batch modify files Haskell
我正在尝试创建一个程序,向目录(及其子目录)中的每个文件添加一个简单的文本 header。我需要使用 ghc 的内置函数来完成此操作(我无法访问 cabal)。
函数的类型签名是
getRecursiveContents :: FilePath -> IO [FilePath]
addHeaderToFile :: String -> FilePath -> IO ()
这两个函数都可以独立工作,但由于类型的原因,我很难结合使用这两个函数。我假设使用地图是执行此操作的正确方法,但到目前为止我还没有成功。
addHeaderToMultiple :: String -> IO [FilePath] -> IO ()
addHeaderToMultiple header files = map (addHeaderToFile header) files
我知道由于使用的类型,这将无法正常工作,但我还没有找到修复它的方法。
从 运行 生成文件列表的 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)
我正在尝试创建一个程序,向目录(及其子目录)中的每个文件添加一个简单的文本 header。我需要使用 ghc 的内置函数来完成此操作(我无法访问 cabal)。
函数的类型签名是
getRecursiveContents :: FilePath -> IO [FilePath]
addHeaderToFile :: String -> FilePath -> IO ()
这两个函数都可以独立工作,但由于类型的原因,我很难结合使用这两个函数。我假设使用地图是执行此操作的正确方法,但到目前为止我还没有成功。
addHeaderToMultiple :: String -> IO [FilePath] -> IO ()
addHeaderToMultiple header files = map (addHeaderToFile header) files
我知道由于使用的类型,这将无法正常工作,但我还没有找到修复它的方法。
从 运行 生成文件列表的 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)