haskell - 如何使这段代码更紧凑和可读?

标签 haskell coding-style

我是一名学习 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.PosixSystem.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/

相关文章:

file - 确保及时关闭文件

haskell - 为什么haskell中函数名重复? (新手)

haskell - 当 Haskell 持久库中预期为 `Int` 时,如何通过 `Key` 获取实体?

haskell - haskell中解压功能的实现

python - 使静态方法显式引用该类

c# - 如何给字典起名字?

java - 如何简化这种解析方法?

c - Visual Studio 2010 运行时检查失败 #3

haskell - Haskell 中的基本求和

c# - 何时为成员添加 'this' (C#) 前缀的好规则是什么?