2011-10-18 11 views
12

To jest mój PIERWSZY program haskell! "wordCount" przyjmuje listę słów i zwraca krotkę z każdym słowem niewrażliwym na wielkość liter w połączeniu z jego liczbą użycia. Wszelkie sugestie dotyczące poprawy czytelności kodu lub wydajności?Prosta liczba słów w 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 

Odpowiedz

24

Gratulujemy pierwszego programu!

Dla czystości: zatrać średniki. Zamiast tego należy użyć nowych nazw modułów hierarchicznych (Data.List, Data.Char). Dodaj podpisy typów. W miarę wygodniejszego komponowania funkcji, eta zawiera definicje funkcji (usuń najbardziej prawe argumenty). na przykład

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

Jeśli chcesz być naprawdę rygorystyczne, używać jawnych list Import:

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

Na wydajność: użyj Data.Map przechowywać skojarzeń zamiast nub i filter. W szczególności zobacz fromListWith i toList. Korzystając z tych funkcji, można uprościć implementację i jednocześnie poprawić wydajność.

+0

Dzięki, dziś wieczorem poprawię te sugestie. Zasłużyłeś na tę karmę :) –

6

Zawsze dobrze jest poprosić doświadczonych programistów o opinię. Mimo to możesz użyć numeru hlint, aby uzyskać opinię na temat drobnych problemów. Poinformuje Cię o importowaniu hierarchicznym, niepotrzebnym nawiasie, alternatywnych funkcjach wyższego rzędu itd.

Odnośnie funkcji, nub1. Jeśli nie podążysz za radą luqui, aby całkowicie usunąć ten parametr, powinienem przynajmniej usunąć nawias wokół xs po prawej stronie równania.

+0

Sądzę, że chodziło ci o lewą stronę zamiast prawą. –

+0

tak, masz rację. – jmg

15

Jednym ze sposobów poprawy czytelności jest próba przyzwyczajenia się do standardowych funkcji. Hoogle jest jednym z narzędzi, które ustawia Haskell dala od reszty świata;)

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 

EDIT: Wyjaśnienie: Więc myślisz o nim jako o łańcuchu odwzorowań:

  • (map toLower) :: String -> String lowercases cały tekst, w celu przypadku niewrażliwości
  • words :: String -> [String] dzieli kawałek tekstu słowami
  • sort :: Ord a => [a] -> [a] sortuje
  • group :: Eq a => [a] -> [[a]] gromadzi elementy identicial na liście, na przykład group [1,1,2,3,3] ->[[1,1],[2],[3,3]]
  • &&& :: (a -> b) -> (a -> c) -> (a -> (b, c)) stosuje się dwie funkcje na tej samej kartce danych, a następnie zwraca krotki wyników. Na przykład: (head &&& length) ["word","word","word"] ->("word", 3) (właściwie &&& jest trochę bardziej ogólnie, ale uproszczone wyjaśnienie pracuje dla tego przykładu)

EDIT: Albo faktycznie, poszukaj pakietu „multiset” na Hackage.

+3

streszczenie implementacja funkcjonalna nie nadaje się dla początkującego (np. '&&&'), również bez wyjaśnienia. -1 – luqui

+2

OK, dodajmy wyjaśnienie T_T – Phil

+4

znacznie lepiej. Podoba mi się kolejność łańcucha, a Ty zawierasz sygnatury typu, abyśmy mogli zobaczyć, jak dane zmieniają się w trakcie łańcucha. – luqui