Haskell - odwracanie list (dwie definicje)

0

Funkcję odwracającą listę można zapisać w takiej postaci:

reverse [] = []
reverse (x:xs) = reverse xs ++ [x]

Taka definicja jest jak najbardziej zrozumiała, ale spotkałem się też z czymś takim:

reverse = aux [] where
     aux ys [] = ys
     aux ys (x:xs) = aux (x:ys) xs

Co jest dla mnie kompletnie niezrozumiałe. Czym jest aux, po co jest słówko where i dlaczego wywołujemy to w taki sposób: reverse [1,2,3] ??

0
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]

Zrozumiała i prosta, niestety \Theta(n^2), tzn. wolna.

reverse = aux [] where
     aux ys [] = ys
     aux ys (x:xs) = aux (x:ys) xs

Czym jest aux - aux - funkcja pomocnicza.

Równoważnie (poza wprowadzeniem reverse' poziom wyżej dla czytelności):

reverse = reverse' []

reverse' ys [] = ys
reverse' ys (x:xs) = reverse' (x:ys) xs

po co jest słówko where i dlaczego wywołujemy to w taki sposób: reverse [1,2,3] - nie rozumiem pytania, do czego służy where chyba wiesz. Tak samo, jak inaczej by to miało być wywoływane.

Ad. dlaczego tak pisać - taka wersja jest szybka (i nie przesadzaj z tą nieczytelnością, dość idiomatyczna - to dość typowy wzorzec).
Ad. dlaczego/jak to działa - pierwszy argument reverse' to już odwrócony fragment listy - rozpisz sobie dla kilku przykładów:

reverse [1, 2, 3, 4] = 
reverse' [] [1, 2, 3, 4] =
reverse' [1] [2, 3, 4] =
reverse' [2, 1], [3, 4] =
reverse' [3, 2, 1] [4] =
reverse' [4, 3, 2, 1] =
[4, 3, 2, 1]
0

Nie do końca chyba mnie zrozumiałeś.

Jeśli napiszę funkcję silnia:

silnia 0 = 1
silnia n = n*silnia (n-1)

to widzę co jest argumentem tej funkcji: n.

A w przypadku tego ulepszonego reverse mam: reverse = aux [] where ... i gdzie tu niby są jakieś argumenty? Gdyby było reverse x:xs = aux [] where ... to bym jeszcze rozumiał, ale tak zupełnie nie wiem o co chodzi.

Dalej nie rozumiem funkcji aux. Najpierw w pierwszej linijce jest aux [] a poniżej aux dostaje już dwa argumenty. Możesz mi to jakoś wyjaśnić albo odesłać do jakiś źródeł?

0

Zapis

reverse = aux []

stosuje mechanizm języka o nazwie partial application. Równie dobrze można napisać:reverse xs = aux [] xs

albo<code class="haskell">reverse = \xs -> aux [] xs

Wszystkie te 3 zapisy znaczą to samo.

1 użytkowników online, w tym zalogowanych: 0, gości: 1