Гибкое количество аргументов для программы на Haskell

Я использую System.FilePath.Find модуль filemanip для рекурсивного поиска всех файлов, которые мне нужно обработать (здесь я буду использовать просто печать на консоли в качестве действия для выполнения, чтобы не путать вещи). Теперь этот код:

import System.Environment (getArgs)
import System.FilePath (FilePath)
import System.Directory (doesDirectoryExist, getDirectoryContents,doesFileExist)
import Control.Monad
import System.FilePath.Find (find,always,fileType,(==?),FileType(..),(&&?),extension)


main= do 
    [dbFile,input]<- getArgs
    files <- findFiles input
    mapM_ putStrLn files 
    return ()

searchExtension :: String
searchExtension = ".hs"

findFiles :: FilePath -> IO [String]
findFiles = find (always) ( fileType ==? RegularFile &&? extension ==? searchExtension)

хорошо работает с этим вызовом

./myprog tet .

В этом случае get Аргумент игнорируется (будет выходной файл базы данных позже), а второй аргумент ищется для рекурсивного поиска подходящих файлов. Это также позволяет мне указать только один файл, который просто идеален!

НО, хотелось бы уточнить

./myprog тет путь1 путь2 путь4 файл1

но это конечно терпит неудачу в сопоставлении с образцом:

./myprog tet .,

myprogt: ошибка пользователя (Ошибка соответствия шаблона в выражении do в myprog.hs:11:9-22)

Теперь, как мне сделать эту программу более гибкой, чтобы я мог использовать более двух аргументов?

Извините за вопрос, на самом деле, но мои знания Haskell ограничены, но увеличиваются для каждой новой вещи, которую я должен сделать в своем первом проекте.

1 ответ

Решение

Ну, вы можете использовать другой шаблон, как:

(dbFile:inputs) <- getArgs

где dbFile будет соответствовать первому аргументу, переданному в то время как inputs будет соответствовать любому числу имен файлов (даже 0, Если вы хотите использовать хотя бы одно имя пути inputs@(_:_) вместо простого inputs).

Тогда вы можете использовать mapM звонить findFiles для каждого пути в inputs:

files <- mapM findFiles input
mapM_ putStrLn $ concat files

Вместо mapM Вы могли бы изменить findFiles принять [FilePath] аргумент вместо простого FilePath,


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

Другие вопросы по тегам