Idąc krok po kroku:
list2 = list of numbers
Weźmiemy to jak dana, więc list2
nadal jest tylko lista numerów.
for i from 0 to N // N being a positive integer
Poprawny sposób to zrobić w Haskell jest na ogół z listy. Lenistwo oznacza, że wartości będą obliczane tylko wtedy, gdy są używane, więc przechodzenie przez listę od 0 do N kończy się tak samo jak pętla, którą tu masz. Więc tylko [0..n]
załatwi sprawę; musimy tylko dowiedzieć się, co z tym zrobić.
for each number in list2
Biorąc pod uwagę „dla każdego”, możemy wywnioskować, że musimy przechodzić całość list2
tutaj; co z tym robimy, jeszcze nie wiemy.
if number == i, add to list1
Budujemy list1
jak idziemy, tak idealnie, że chcemy być ostateczny wynik wyrażenia. Oznacza to również, że na każdym etapie rekurencyjnym chcemy, aby wynik był list1
, który mamy "do tej pory". Aby to zrobić, musimy upewnić się, że wyniki każdego kroku są przekazywane razem z nami.
więc schodzimy do mięsa IT:
Funkcja filter
znajdzie wszystkie elementy na liście pasujących jakieś orzeczenie; użyjemy tutaj filter (== i) list2
, aby znaleźć to, czego szukamy, a następnie dołączyć do wyniku poprzedniego kroku. Tak więc każdy krok będzie wyglądał następująco:
step :: (Num a) => [a] -> a -> [a]
step list1 i = list1 ++ filter (== i) list2
To obsługuje pętlę wewnętrzną. Odwracając się na zewnątrz, musimy uruchomić to dla każdej wartości i
z listy [0..n]
, przy czym wartość list1
jest przekazywana w każdym kroku.To jest dokładnie to, co krotnie funkcje są dla iw tym przypadku step
jest dokładnie to, czego potrzebujemy dla lewego fałdu:
list2 :: (Num a) => [a]
list2 = -- whatever goes here...
step :: (Num a) => [a] -> a -> [a]
step list1 i = list1 ++ filter (== i) list2
list1 :: (Num a) => a -> [a]
list1 n = foldl step [] [0..n]
Jeśli zastanawiasz się, gdzie rekurencji jest filter
i foldl
robią to za nas oboje . Zasadniczo lepiej unikać bezpośredniej rekursji, gdy istnieją funkcje wyższego poziomu, aby zrobić to za Ciebie.
Powiedział, że tu jest głupi algorytm na wiele sposobów, ale nie chce się w to, bo wydawało się, że to odciągnąć od rzeczywistego pytanie więcej niż miałoby to pomóc.
Dlaczego nie użyć 'concatMap' zamiast składania jawnego kroku konkatenacji? – bdonlan
Należy zauważyć, że w tym przypadku można użyć funkcji sprawdzania list: [numer | i <- [1..N], numer <-list2, i == numer], który jest bezpośrednim tłumaczeniem Twojego pseudokodu. – ysdx
Dzięki za wspaniałą odpowiedź. Zdaję sobie sprawę, że opublikowany przeze mnie fragment jest dziwny ... Drastycznie ogoliłem wszelkie znaczenie z tego. Jest to część ćwiczenia sortowania radix, które robię. –