前言
上一篇《我的第一个面向需求的Haskell程序》文章中的Haskell程序还存在一个问题: 程序只打印出了文件中有没有重复的元素但是并没有告知是哪一个元素重复了,重复了几次也没有打印出来。 所以我继续优化下上篇文章中的Haskell程序,现在这段程序变成了下面这样
代码
代码语言:javascript复制module Main where
import Data.List.Split
import Data.List
import System.IO
import System.Environment
main = do
args <- getArgs
check args
check::[String] -> IO ()
check [filename] = do
contents <- readFile filename
mapM_ printRepeat $ fmap ((x:xs) -> (x, 1 length xs)) $ group $ splitOn "rn" contents
putStrLn "check done"
check x = do
putStrLn "请输入文件名"
printRepeat::(String, Int) -> IO()
printRepeat (word, num)
| num > 1 = putStrLn $ word " repeated " (show num) " times."
| otherwise = return ()
使用
代码语言:javascript复制$ cabal build
$ ./dist-newstyle/build/x86_64-osx/ghc-8.8.4/repeat-0.1.0.0/x/repeat/build/repeat/repeat test.txt
joM2qWfjOJc repeated 2 times.
check done
解释
首先我们使用split
包提供的splitOn
函数按照换行符将文件内容切分为[String],现在我们有了:
["abc", "abc", "def", "ghi", "def"]
然后使用group
函数聚合下这个List,得到:
[["abc", "abc", "abc"], ["def", "def"], ["ghi"]]
再通过fmap ((x:xs) -> (x, 1 length xs))
即map一个lambda表达式到这个List上,将这个List中的每个元素转为元组,得到:
[("abc", 3), ("def", 2), ("ghi", 1)]
至此我们实际做了一个WordCount
程序…
接下来调用printRepeat函数打印出来结果就OK了