我对 Haskell 并不陌生,但在现实世界中并没有太多使用它。
所以我想做的是从某些文件夹开始找到所有 git 存储库。基本上我正在尝试这样做find . -type d -exec test -e '{}/.git' ';' -print -prune
通过使用 Haskell 并发功能只会更快。
这是我到目前为止所得到的。
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 https://www.stackage.org/haddock/lts-7.14/async-2.1.1/Control-Concurrent-Async.html#v:mapConcurrently有这个功能的mapConcurrently :: Traversable t => (a -> IO b) -> t a -> IO (t b)
这让我想到我需要的是生成反映文件夹结构的惰性树数据结构。然后同时过滤它isGitRepo
然后将其折叠到列表中并打印出来。
嗯,我当然知道怎么做data FTree = Node String [FTree]
或类似的事情,但我有疑问。
如何同时生产?如何在遍历树时产生绝对路径?诸如此类的问题。
这让我想到我需要的是生成反映文件夹结构的惰性树数据结构。
我不确定你是否需要一个树结构。你could制作一个这样的中间结构,但你也可以不使用它。关键是你需要有O(1)
附加(合并您的结果)。差异列表(例如dlist https://hackage.haskell.org/package/dlist) 做这个。
如何同时生产?
你已经明白了:使用mapConcurrently
!
如何在遍历树时产生绝对路径?
listDirectory http://hackage.haskell.org/package/directory-1.3.0.0/docs/System-Directory.html#v: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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)