Jestem całkowicie nowy dla Haskella, więc przepraszam, jeśli pytanie jest głupie.Moneta trybu rekurencyjnego do gromadzenia wartości podczas budowania listy?
Co chcę zrobić, to rekurencyjnie zbudować listę podczas w tym samym czasie budowanie skumulowanej wartości w oparciu o rekurencyjne połączenia. To jest dla problemu, który robię dla kursu Coursera, więc nie opublikuję dokładnego problemu, ale coś analogicznego.
Powiedz na przykład chciałem wziąć listę int i double każdy (ignorując dla celów przykładu, że może po prostu wykorzystać map
), ale również chciał policzyć ile razy liczba ' 5 'pojawi się na liście.
więc zrobić podwojenie mogę to zrobić:
foo [] = []
foo (x:xs) = x * 2 : foo xs
tej pory tak łatwo. Ale w jaki sposób mogę również sprawdzić, ile razy x
ma pięć? Najlepszym rozwiązaniem mam jest użycie wyraźny akumulator jak ten, który mi się nie podoba, ponieważ odwraca listy, więc trzeba zrobić odwrotnie na koniec:
foo total acc [] = (total, reverse acc)
foo total acc (x:xs) = foo (if x == 5 then total + 1 else total) (x*2 : acc) xs
Ale czuję się jak to powinno być łatwiejsze do obsłużenia przez monadę State
, której wcześniej nie używałem, ale kiedy próbuję skonstruować funkcję, która pasuje do wzorca, który widziałem, utknąłem z powodu rekursywnego połączenia z foo
. Czy jest lepszy sposób na zrobienie tego?
EDYCJA: Potrzebuję tego do pracy na bardzo długich listach, więc wszelkie wywołania rekurencyjne muszą być również rekursywne. (Przykład, który tutaj mam, jest rekursywny w ogonach dzięki "rekursji modulo cons" Haskella).
pokrewne pytanie: [ "optymalizacja Tail gwarancja - kodowanie pętla w Haskell"] (http://stackoverflow.com/q/9149183/ 849891). –
W jakim sensie Twój przykładowy rekurencyjny ogon? Uważam, że gromadzi się w nim mnóstwo i powoduje "wyciek pamięci". Nawet samo wywołanie 'reverse' wydaje się wystarczające, by spowodować wyciek pamięci. – yairchu
Kiedy mówię * to rekurencyjny * ogon, miałem na myśli prosty przykład mapy, a nie drugi fragment kodu. TBH Ciężko pracuję nad tym, co jest i co nie jest wydajnym kodem w Haskell - wygląda na to, że działa zupełnie inaczej niż w jakimkolwiek innym języku, którego używałem! Myślę, że muszę jeszcze trochę o tym przeczytać :-) – Russell