Однією з найважливіших причин явного використання цього rec
є пов'язаність з висновком типу Хіндлі-Мілнера, який лежить в основі всіх статично набраних функціональних мов програмування (хоч і змінених і розширених різними способами).
Якщо у вас є визначення let f x = x
, ви очікуєте, що воно має тип 'a -> 'a
і буде застосовано для різних 'a
типів у різних точках. Але в рівній мірі, якщо ви пишете let g x = (x + 1) + ...
, ви б розраховували, що x
до вас ставляться як int
до решти тіла g
.
Спосіб, яким можна дійти висновку Хіндлі-Мілнера, полягає в явному кроці узагальнення . У певні моменти при обробці вашої програми система типів зупиняється і каже "нормально, типи цих визначень будуть узагальнені в цей момент, так що коли хтось їх використовує, будь-які змінні вільного типу в їхньому вигляді будуть свіжими ідентифікованими, і таким чином не заважатиме жодним іншим способам використання цього визначення. "
Виявляється, розумним місцем для цього узагальнення є перевірка взаємно рекурсивного набору функцій. Раніше, і ви занадто багато узагальнюєте, призводите до ситуацій, коли типи можуть насправді стикатися. Пізніше, і ви будете узагальнювати занадто мало, роблячи визначення, які не можна використовувати з кількома типами даних.
Отже, враховуючи, що перевіряючий тип повинен знати про те, які набори визначень взаємно рекурсивні, що це може зробити? Одна з можливостей - це просто зробити аналіз залежності всіх визначень у межах сфери та переупорядкувати їх на найменші можливі групи. Haskell насправді робить це, але в таких мовах, як F # (і OCaml і SML), які мають необмежені побічні ефекти, це погана ідея, тому що вона може змінити побічні ефекти також. Тому замість цього він просить користувача чітко позначити, які визначення є взаємно рекурсивними, і, таким чином, шляхом розширення, де має відбуватися узагальнення.