2013-06-10 16 views
13

Powtórz is defined następująco:Dlaczego powtarzanie jest zdefiniowane w Preludium takim, jakie jest?

repeat :: a -> [a] 
repeat x = xs where xs = x:xs 

Czy jest jakiś powód, że poniższe nie jest używany?

repeat :: a -> [a] 
repeat x = x : repeat x 

(Oczywiście istnieje wiele równoważne definicje dla wielu funkcji Prelude, ale mój ostatni opis prostu czuje się znacznie bardziej oczywiste. Zastanawiam się, czy istnieje wydajność lub styl powodem tak jest.)

+6

[Zobacz moją odpowiedź tutaj] (http://stackoverflow.com/questions/16632143/why-recursive-let-make-space-effcient/16632403#16632403). Definicja tam używa 'let', ale to samo zachowanie z' where'. – hammar

Odpowiedz

20

To jest z powodów wydajności i złożoności przestrzeni.

Pierwsza wersja kodu wykorzystuje jawne udostępnianie; w zasadzie wygląda jak jednoczęściowa, kołowa, połączona lista w pamięci (xs w kodzie jest węzłem listy, który ma x jako wartość, a jego ogon wskazuje na ten sam węzeł listy). Gdy ocenisz coraz więcej elementów listy, będzie to wymagało powtarzania tego samego węzła.

W przeciwieństwie do drugiej wersji, tworzona jest lista, która faktycznie rośnie w pamięci, ponieważ jest oceniana, ponieważ różne wywołania repeat x są zawsze przeliczane (i nie są pamiętane). Na końcu wygenerowanej listy zawsze pojawi się kolejny niedoszacowany thunk.

Powiązane problemy