2011-10-18 32 views
12

這是我的第一個haskell程序! 「wordCount」接收單詞列表並返回一個元組,每個不區分大小寫的單詞與其使用次數配對。任何關於代碼可讀性或性能改進的建議?簡單的字數在haskell

import List; 
import Char; 
uniqueCountIn ns xs = map (\x -> length (filter (==x) xs)) ns 
nubl (xs) = nub (map (map toLower) xs) -- to lowercase 
wordCount ws = zip ns (uniqueCountIn ns ws) 
    where ns = nubl ws 

回答

24

恭喜您的第一個計劃!

清潔度:丟失分號。改爲使用新的分層模塊名稱(Data.ListData.Char)。添加類型簽名。當你更熟悉函數組合時,eta會收縮你的函數定義(刪除最右邊的參數)。例如

nubl :: [String] -> [String] 
nubl = nub . map (map toLower) 

如果你想成爲真正嚴格,使用顯式導入列表:

import Data.List (nub) 
import Data.Char (toLower) 

出於性能:使用Data.Map存儲的關聯,而不是nubfilter。具體見fromListWithtoList。使用這些函數可以簡化實現並同時提高性能。

+0

謝謝,今晚我會解決這些建議。你贏得了這個業力:) –

2

添加函數的類型簽名真的會有所幫助。

6

向經驗豐富的開發人員反饋意見總是很好的。不過,您可以使用hlint來獲取有關小規模問題的反饋。它會告訴你關於等級進口,不含義的括號,替代的高階函數等。

關於函數,nub1。如果你不遵循luqui的建議來完全刪除參數,我會至少刪除等式右邊xs的括號。

+0

我想你的意思是左手而不是右手。 –

+0

是的,你是對的。 – jmg

15

提高可讀性的方法之一是嘗試習慣標準功能。 Hoogle是從世界其他地方設置哈斯克爾分開的工具之一;)

import Data.Char (toLower) 
import Data.List (sort, group) 
import Control.Arrow ((&&&)) 

wordCount :: String -> [(String, Int)] 
wordCount = map (head &&& length) . group . sort . words . map toLower 

編輯:說明:所以你認爲它是映射的鏈:

  • (map toLower) :: String -> String小寫全文,案例 不敏感
  • words :: String -> [String]將一段文字拆分成詞
  • sort :: Ord a => [a] -> [a]排序
  • group :: Eq a => [a] -> [[a]]集列表中的identicial元件,例如,group [1,1,2,3,3] - >[[1,1],[2],[3,3]]
  • &&& :: (a -> b) -> (a -> c) -> (a -> (b, c))在同一塊數據的適用兩種功能,然後返回 結果的元組。例如:(head &&& length) ["word","word","word"] - >("word", 3)(實際上&&&是有點更普遍的,但爲了簡化說明適用於本示例)

編輯:或實際,尋找「多重集」包上Hackage

+3

不適合初學者的抽象函數實現(例如'&&&'),也沒有解釋。 -1 – luqui

+2

好的,讓我加上解釋T_T – Phil

+4

好多了。我喜歡鏈的順序,並且包含了類型簽名,所以我們可以看到數據如何通過鏈來轉換。 – luqui