Nie twierdzę, że w ogóle to rozumiem, ale jeśli to komuś pomaga ...
Rozważ definicję fix. fix f = let x = f x in x. Zadziwiająca część xjest zdefiniowana jako f x. Ale pomyśl o tym przez chwilę.
x = f x
Ponieważ x = fx, możemy podstawić wartość xpo prawej stronie tego, prawda? Więc dlatego...
x = f . f $ x
x = f . f . f $ x
x = f . f . f . f . f . f . f . f . f . f . f $ x
Tak więc sztuczka polega na tym, że aby zakończyć, ftrzeba wygenerować jakąś strukturę, tak aby późniejszy fwzorzec mógł dopasować tę strukturę i zakończyć rekursję, bez faktycznego dbania o pełną "wartość" swojego parametru (?)
Chyba że, oczywiście, chcesz zrobić coś takiego, jak stworzenie nieskończonej listy, jak zilustrowano luqui.
Silnia wyjaśnienia TomMD jest dobra. Podpis typu poprawki to (a -> a) -> a. Innymi słowy, typ podpisu dla (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1)to . Więc możemy tak powiedzieć . W ten sposób fix przyjmuje naszą funkcję, która jest lub naprawdę, i zwróci wynik typu , innymi słowy, inną funkcję!(b -> b) -> b -> b(b -> b) -> (b -> b)a = (b -> b)a -> a(b -> b) -> (b -> b)ab -> b
Czekaj, myślałem, że powinien zwrócić stały punkt ... a nie funkcję. Cóż, w pewnym sensie (ponieważ funkcje to dane). Możesz sobie wyobrazić, że dało nam to ostateczną funkcję znajdowania silni. Daliśmy mu funkcję, która nie wiedziała, jak się powtarzać (stąd jeden z jej parametrów jest funkcją używaną do rekurencji), i fixnauczyliśmy ją, jak się powtarzać.
Pamiętasz, jak powiedziałem, że fmusi wygenerować jakąś strukturę, aby później fmożna było dopasować wzorzec i zakończyć? Cóż, to chyba nie do końca w porządku. TomMD zilustrował, jak możemy rozszerzyć, xaby zastosować funkcję i przejść do przypadku podstawowego. Do swojej funkcji użył warunku if / then i to właśnie powoduje zakończenie. Po wielokrotnych zamianach inczęść całej definicji fixostatecznie przestaje być definiowana w kategoriach xi wtedy jest obliczalna i kompletna.
fix errorghci i poczuć się dobrze ze sobą”.