Я не претендую на те, щоб це взагалі розуміти, але якщо це комусь допомагає ... тоді їппі.
Розглянемо визначення fix. fix f = let x = f x in x. Приголомшлива частина - це те, що xвизначається як f x. Але подумайте про це хвилинку.
x = f x
Оскільки x = fx, то ми можемо підставити значення xправоруч від цього, так? Тож ...
x = f . f $ x
x = f . f . f $ x
x = f . f . f . f . f . f . f . f . f . f . f $ x
Отже, фокус полягає в тому, що для того, щоб припинити, fпотрібно створити якусь структуру, щоб пізнішеf шаблон міг збігатися з цією структурою і припиняти рекурсію, насправді не дбаючи про повне «значення» її параметра (?)
Якщо, звичайно, ви не захочете зробити щось на зразок створення нескінченного списку, як це ілюструє luqui.
Пояснення факторіалів TomMD добре. Тип підпису FIX є (a -> a) -> a. Іншими словами, підпис типу - (\recurse d -> if d > 0 then d * (recurse (d-1)) else 1)це . Тож ми можемо це сказати . Таким чином, fix приймає нашу функцію, яка є , або насправді, і повертає результат типу , іншими словами, іншими словами, іншої функції!(b -> b) -> b -> b(b -> b) -> (b -> b)a = (b -> b)a -> a(b -> b) -> (b -> b)ab -> b
Зачекайте, я думав, це повинно було повернути фіксовану точку ... а не функцію. Ну, це так, начебто (оскільки функції - це дані). Ви можете собі уявити, що це дало нам остаточну функцію для пошуку факторіалу. Ми дали йому функцію, яка не знає, як повторити (отже, одним із параметрів для неї є функція, яка використовується для рекурсії), і fixнавчили її, як повторити.
Пам'ятаєте, як я сказав, що це fмає генерувати якусь структуру, щоб пізніший fшаблон міг збігатися і закінчуватися? Ну це не зовсім правильно, я здогадуюсь. TomMD проілюстрував, як ми можемо розширити, xщоб застосувати функцію і зробити крок до базового випадку. Для своєї функції він використовував if / then, і саме це спричиняє припинення. Після багаторазових замін inчастина цілого визначення fixврешті-решт перестає визначатися з точки зору, xі саме тоді воно є обчислювальним та повним.
fix errorghci і відчувати себе добре".