Một lý do quan trọng cho việc sử dụng rõ ràng rec
là liên quan đến suy luận kiểu Hindley-Milner, làm cơ sở cho tất cả các ngôn ngữ lập trình hàm được định kiểu tĩnh (mặc dù đã thay đổi và mở rộng theo nhiều cách khác nhau).
Nếu bạn có một định nghĩa let f x = x
, bạn sẽ mong đợi nó có kiểu 'a -> 'a
và có thể áp dụng cho các 'a
kiểu khác nhau ở các điểm khác nhau. Nhưng tương tự, nếu bạn viết let g x = (x + 1) + ...
, bạn sẽ x
được coi là một int
phần còn lại của phần còn lại củag
.
Cách suy luận của Hindley-Milner giải quyết sự khác biệt này là thông qua một bước tổng quát hóa rõ ràng . Tại một số điểm nhất định khi xử lý chương trình của bạn, hệ thống kiểu dừng lại và nói "được rồi, các loại định nghĩa này sẽ được tổng quát hóa vào thời điểm này, để khi ai đó sử dụng chúng, mọi biến kiểu tự do trong kiểu của chúng sẽ được làm mới khởi tạo và do đó sẽ không ảnh hưởng đến bất kỳ cách sử dụng nào khác của định nghĩa này. "
Nó chỉ ra rằng nơi hợp lý để thực hiện tổng quát hóa này là sau khi kiểm tra một bộ hàm đệ quy lẫn nhau. Bất kỳ điều gì sớm hơn, và bạn sẽ khái quát hóa quá nhiều, dẫn đến tình huống mà các loại thực sự có thể va chạm. Bất cứ lúc nào sau đó, và bạn sẽ khái quát quá ít, tạo ra các định nghĩa không thể được sử dụng với nhiều kiểu thuyết minh.
Vì vậy, với điều kiện trình kiểm tra kiểu cần biết về các tập hợp định nghĩa nào là đệ quy lẫn nhau, nó có thể làm gì? Một khả năng là chỉ cần thực hiện phân tích sự phụ thuộc vào tất cả các định nghĩa trong một phạm vi và sắp xếp lại chúng thành các nhóm nhỏ nhất có thể. Haskell thực sự làm được điều này, nhưng trong các ngôn ngữ như F # (và OCaml và SML) có tác dụng phụ không hạn chế, đây là một ý tưởng tồi vì nó cũng có thể sắp xếp lại các tác dụng phụ. Vì vậy, thay vào đó, nó yêu cầu người dùng đánh dấu rõ ràng các định nghĩa nào là đệ quy lẫn nhau và do đó bằng cách mở rộng nơi xảy ra tổng quát hóa.