我对haskell并不陌生,但在现实世界中并没有使用它。
所以我想要做的是从一些文件夹开始查找所有git存储库。基本上我只是通过使用haskell并发功能来更快地尝试find . -type d -exec test -e '{}/.git' ';' -print -prune
。
这是我到目前为止所得到的。
import Control.Concurrent.Async
import System.Directory (doesDirectoryExist)
import System.FilePath ((</>))
import System.IO (FilePath)
isGitRepo :: FilePath -> IO Bool
isGitRepo p = doesDirectoryExist $ p </> ".git"
main :: IO ()
main = putStrLn "hello"
我发现此lib具有此功能mapConcurrently :: Traversable t => (a -> IO b) -> t a -> IO (t b)
这让我想到我需要的是生成反映文件夹结构的懒惰树数据结构。然后与isGitRepo
同时过滤它并将其折叠到列表中并打印出来。
好吧,当然我知道如何制作data FTree = Node String [FTree]
或类似的东西,但我有疑问。
如何同时生产?如何在遍历树时产生绝对路径?像这样的问题等等。
答案 0 :(得分:2)
让我想到我需要的是生成反映文件夹结构的懒惰树数据结构。
我不确定你需要一个树形结构。你可以制作一个中间结构,但你也可以在没有一个结构的情况下进行管理。关键是你需要O(1)
追加(结合你的结果)。差异列表(如dlist
)就是这样做的。
如何同时生产?
你已经得到了:使用mapConcurrently
!
如何在遍历树时产生绝对路径?
listDirectory
可让您获取路径中的下一个可能段。您可以通过将每个段附加到现有路径来获取下一个路径(除非现有路径是,否则它们不是绝对路径)。
这是一个有效的功能:
import System.Directory (doesDirectoryExist, listDirectory)
import System.FilePath ((</>), combine)
import System.IO (FilePath)
import Control.Concurrent.Async (mapConcurrently)
import qualified Data.DList as DL
-- | tries to find all git repos in the subtree rooted at the path
findGitRepos :: FilePath -> IO (DL.DList FilePath)
findGitRepos p = do
isNotDir <- not <$> doesDirectoryExist p
if isNotDir
then pure DL.empty -- the path 'p' isn't a directory
else do
isGitDir <- doesDirectoryExist (p </> ".git")
if isGitDir
then pure (DL.singleton p) -- the folder is a git repo
else do -- recurse to subfolders
subdirs <- listDirectory p
repos <- mapConcurrently findGitRepos (combine p `map` subdirs)
pure (DL.concat repos)