2011-07-14 9 views
8

ciąg Jestem nowicjuszem w Haskell, i mam pytanie: napisać kod:Haskell i długość

word_list = ["list", "lol", "wordword"] 
check str = if head str == 'l' then tail str else str 
average wl = (length $ concat $ map check wl) `div` length wl 

ten kod musi usunąć pierwszy symbol „L” w każdym słowie w liście słów, concat otrzymaliśmy słowa , uzyskać długość ciągu wynikowego i div na liczbę słów.

więc w tym kodzie muszę odbierać: 13/3 = 4,333 ... ("listlolwordword" = 15 "istolwordword" = 13) ale otrzymaliśmy tylko 4.

average :: [[Char]] -> Float nie działają , otrzymuję błąd. gdzie mój błąd? ps. przepraszam, mój angielski, proszę

Odpowiedz

12

Funkcja zwraca Int, a funkcja div wykonuje podział całkowity, innymi słowy, upuszcza część ułamkową. Jeśli chcesz Float rezultat, trzeba najpierw przekonwertować wynik z length do Float, a następnie użyć (/) do podziału Zamiast:

word_list = ["list", "lol", "wordword"] 
check str = if head str == 'l' then tail str else str 
average wl = fromIntegral (length $ concat $ map check wl)/fromIntegral (length wl) 

Chociaż jestem w nim, należy rozważyć użycie wzór pasujący w check zamiast np:

check ('l':str) = str 
check str = str 

Ten styl jest zarówno bardziej czytelne i mniej narażone na błędy - na przykład wersja zawiedzie jeśli dany ciąg pusty.

+0

wow. dziękuję bardzo! o dopasowywaniu wzorów: to niesamowite! lubię hasskel więcej każdego dnia :) –

+1

@user: Zauważ, że istnieje również concatMap, więc nie musisz robić "concat $ map". –

+1

i chciałbym zauważyć, że bardziej przejrzystym podejściem jest prawdopodobnie 'suma $ map (length. Check) wl' (chociaż fuzja prawdopodobnie czyni to nieistotnym) – alternative

Powiązane problemy