我是一名学习 Haskell 的 Java 程序员。 我编写了一个小程序,可以在文件中搜索带有特定后缀的单词。
我想看看你的批评。 你有什么建议可以使这段代码更紧凑、更易读?
module Main where
import Control.Monad
import Data.String.Utils
import Data.List
import Data.Char
import System.Directory
import System.FilePath
import System.IO
import System.IO.HVFS.Utils
import Text.Regex
alphaWords :: String -> [String]
alphaWords = words . map (\c -> if isAlpha c then c else ' ') -- by ephemient
-- was:
-- words2 s = case dropWhile isSpace2 s of
-- "" -> []
-- ss -> w : words2 sss
-- where (w, sss) = break isSpace2 ss
-- where isSpace2 = not . isAlpha
findFiles :: FilePath -> IO [FilePath]
findFiles path = do
cur_path <- getCurrentDirectory
files <- recurseDir SystemFS $ normalise $ combine cur_path path
filterM doesFileExist files
wordsWithSuffix :: String -> String -> [String]
wordsWithSuffix suffix text =
let tokens = (nub . alphaWords) text
endswithIgnoringCase = endswith suffix . map toLower
in filter endswithIgnoringCase tokens
searchWords :: String -> String -> [String] -> IO [String]
searchWords suffix path exts = do
let isSearchable = (`elem` exts) . takeExtension -- by yairchu
--was let isSearchable s = takeExtension s `elem` exts
--files <- filterM (fmap isSearchable) $ findFiles path -- by ephemient (compile error)
files <- liftM (filter isSearchable) $ findFiles path
wordsPerFile <- forM files $ fmap (wordsWithSuffix suffix) . readFile -- by ephemient
-- was: wordsPerFile <- forM files (\x -> liftM (wordsWithSuffix suffix) (readFile x))
return . sort . nub $ concat wordsPerFile -- by ephemient
-- was: return $ (sort . nub . concat) wordsPerFile
main = do
words <- searchWords "tick" "/path/to/src" [".as", ".java", ".mxml"]
print $ length words
putStrLn $ unlines words
更新:我已经修复了 2 个使用“hlint”发现的详细问题,感谢@yairchu
更新 2: 更多修复。谢谢@ephemient
更新 3: 一个小修复。谢谢@yairchu,不能使用你所有的代码——对于 Java 开发人员来说太难了
最佳答案
不要import System.FilePath.Posix
如果你不需要。 System.FilePath
导出 System.FilePath.Posix
或 System.FilePath.Windows
根据您正在编译的平台。
您的words2
实现很好,但没有任何解释为什么它会做什么。这更不言自明,效率差异并不显着。
alphaWords = words . map (\c -> if isAlpha c then c else ' ')
searchWords
的小改进:
- wordsPerFile <- forM files (\x ->
- liftM (wordsWithSuffix suffix) (readFile x))
+ wordsPerFile <- forM files $ fmap (wordsWithSuffix suffix) . readFile
- return $ (sort . nub . concat) wordsPerFile
+ return . sort . nub $ concat wordsPerFile
在 let
中键入注释除非类型检查器真的需要帮助,否则构造并不常见……但如果我注意它们,我就不会犯我之前尝试移动 isSearchable
的错误。 :)
另外,在 main
,我会改变这个:
- putStrLn $ unlines words
+ mapM_ putStrLn words
我不熟悉 MissingH 公开的模块;是 System.IO.HVFS.Utils.recurseDir
懒惰的?如果没有,添加 System.IO.Unsafe.unsafeInterleaveIO
遍历大型目录树时可能有助于减少内存消耗。
关于haskell - 如何使这段代码更紧凑和可读?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1092783/