Tôi đã gặp phải một số hành vi không mong muốn từ trình biên dịch F # gần đây. Tôi đã có thể tìm thấy một cách giải quyết khác, nhưng hành vi ban đầu cản trở tôi và tôi muốn xem liệu có ai có thể giúp tôi hiểu nguyên nhân gây ra nó hay không.Tại sao bộ biên dịch F # đôi khi có chức năng tổng quát không chính xác?
Một hàm mà tôi đã định nghĩa là không chung chung đã trở thành chung chung, điều này ảnh hưởng đến khả năng của hàm chia sẻ trạng thái giữa nhiều lần gọi. Tôi đơn giản hóa use-case của tôi xuống như sau:
let nextId =
let mutable i = 0
let help (key:obj) =
i <- i + 1
i
help
nextId "a" // returns 1
nextId "b" // also returns 1!!!!
Tại sao nextId của loại 'a -> int thay vì obj -> int? Rõ ràng việc khái quát hóa cũng chịu trách nhiệm về lỗi mà nó trả về 1 nhiều lần, nhưng tại sao sự khái quát hóa lại xảy ra ngay từ đầu?
Lưu ý rằng nếu tôi định nghĩa nó mà không cần đặt tên cho các hàm lồng nhau, nó hoạt động như mong đợi trong việc đưa ra Id duy nhất:
let nextId =
let mutable i = 0
fun (key:obj) ->
i <- i + 1
i
nextId "a" // returns 1
nextId "b" // returns 2
Nhưng ngay cả bí ẩn hơn, với định nghĩa này, F # Interactive không thể quyết định xem nextId là một (obj -> int) hoặc ('a -> int). Khi tôi lần đầu tiên xác định nó tôi nhận được
val nextId: (obj -> int)
nhưng nếu tôi chỉ đơn giản là eval
nextId
tôi nhận được
val nó: (' a -> int)
Điều gì đang xảy ra ở đây và tại sao chức năng đơn giản của tôi lại tự động nói chung ized?