2015-04-29 6 views
1

Я пытаюсь создать программу, которая добавляет простой текстовый заголовок для каждого файла в каталоге (и его подкаталогах). Мне нужно сделать это, просто используя встроенные функции из ghc (я не могу получить доступ к cabal).Пакетное изменение файлов Haskell

Сигнатура типа функции являются

getRecursiveContents :: FilePath -> IO [FilePath] 

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

Они оба работают независимо друг от друга тонкой, но я изо всех сил, чтобы использовать эти две функции в сочетании из-типов. Я предположил, что использование карты было бы правильным способом сделать это, но до сих пор я не увенчался успехом.

addHeaderToMultiple :: String -> IO [FilePath] -> IO() 
addHeaderToMultiple header files = map (addHeaderToFile header) files 

Я понимаю, что это не сработает из-за используемых типов, но я не нашел способ исправить это.

+2

Посмотрите 'mapM_ :: Monad m => (a -> mb) -> [a] -> m()'. –

ответ

4

Start, выполнив действие ввода-вывода, продуцирующей список файлов:

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() 

Мы попали проблемы в последней строке, которая строит список действий ввода-вывода, а не запускать их. Мы могли бы использовать вспомогательную функцию:

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) 
+0

Это прекрасно работало и благодарило за то, что объяснил шаги на этом пути, и это стало намного легче понять. – jjcohen

Смежные вопросы