Haskell - 打印元组列表

时间:2015-05-22 04:46:17

标签: list haskell tuples

我有一个元组列表:

[(String, Int)]

如何打印显示如下:

String : Int
String : Int
String : Int
...

我对Haskell很新,所以请尽可能清楚。谢谢!

更新:以下是我的程序代码现在的样子:

main = do  
    putStrLn "********* Haskell word frequency counter *********"
    putStrLn ""
    conts <- readFile "text.txt"
    let lowConts = map toLower conts
    let counted = countAllWords (lowConts)
    let sorted = sortTuples (counted)
    let reversed = reverse sorted
    putStrLn "Word : Count"
    mapM_ (printTuple) reversed

-- Counts all the words.
countAllWords :: String -> [(String, Int)]
countAllWords fileContents = wordsCount (toWords (noPunc fileContents))

-- Splits words and removes linking words.
toWords :: String -> [String]
toWords s = filter (\w -> w `notElem` ["and","the","for"]) (words s)

-- Remove punctuation from text String.
noPunc :: String -> String
noPunc xs = [ x | x <- xs, not (x `elem` ",.?!-:;\"\'") ]

-- Counts, how often each string in the given list appears.
wordsCount :: [String] -> [(String, Int)]
wordsCount xs = map (\xs -> (head xs, length xs)) . group . sort $ xs

-- Sort list in order of occurrences.
sortTuples :: [(String, Int)] -> [(String, Int)]
sortTuples sort = sortBy (comparing snd) sort


printTuple :: Show a => [(String, a)] -> IO ()
printTuple xs = forM_ xs (putStrLn . formatOne)

formatOne :: Show a => (String, a) -> String
formatOne (s,i) = s ++ " : " ++ show i

它将此错误返回给我:

fileToText.hs:18:28:
Couldn't match type ‘(String, Int)’ with ‘[(String, a0)]’
Expected type: [[(String, a0)]]
  Actual type: [(String, Int)]
In the second argument of ‘mapM_’, namely ‘reversed’
In a stmt of a 'do' block: mapM_ (printTuple) reversed

感谢您的帮助!

1 个答案:

答案 0 :(得分:6)

让我们从格式化一个项目开始:

formatOne :: Show a => (String, a) -> String
formatOne (s,i) = s ++ " : " ++ show i

现在您可以使用此功能(例如)与forM_中的Control.Monad将其打印到此屏幕forM_,因为我们希望成为在IO-Monad中 - 因为我们将使用putStrLn):

Prelude> let test = [("X1",4), ("X2",5)]
Prelude> import Control.Monad (forM_)
Prelude Control.Monad> forM_ test (putStrLn . formatOne)
X1 : 4
X2 : 5

在文件中你会像这样使用它:

import Control.Monad (forM_)

printTuples :: Show a => [(String, a)] -> IO ()
printTuples xs = forM_ xs (putStrLn . formatOne)

formatOne :: Show a => (String, a) -> String
formatOne (s,i) = s ++ " : " ++ show i

编译文件

总的来说这里是你的代码版本,它至少会编译(不能在没有文本文件的情况下测试它);)

import Control.Monad (forM_)
import Data.Char (toLower)
import Data.List (sort, sortBy, group)
import Data.Ord (comparing)

main :: IO ()
main = do  
    putStrLn "********* Haskell word frequency counter *********"
    putStrLn ""
    conts <- readFile "text.txt"
    let lowConts = map toLower conts
    let counted = countAllWords lowConts
    let sorted = sortTuples counted
    let reversed = reverse sorted
    putStrLn "Word : Count"
    printTuples reversed

-- Counts all the words.
countAllWords :: String -> [(String, Int)]
countAllWords = wordsCount . toWords . noPunc

-- Splits words and removes linking words.
toWords :: String -> [String]
toWords = filter (\w -> w `notElem` ["and","the","for"]) . words

-- Remove punctuation from text String.
noPunc :: String -> String
noPunc xs = [ x | x <- xs, x `notElem` ",.?!-:;\"\'" ]

-- Counts, how often each string in the given list appears.
wordsCount :: [String] -> [(String, Int)]
wordsCount = map (\xs -> (head xs, length xs)) . group . sort

-- Sort list in order of occurrences.
sortTuples :: [(String, Int)] -> [(String, Int)]
sortTuples = sortBy $ comparing snd

-- print one tuple per line separated by " : "
printTuples :: Show a => [(String, a)] -> IO ()
printTuples = mapM_ (putStrLn . formatTuple)
  where formatTuple (s,i) = s ++ " : " ++ show i

我还删除了编译器警告和HLINTed它(但跳过了Control.Arrow的东西 - 我认为head &&& length在这里不是更易读的选项。