Wpadłem ostatnio na nieoczekiwane zachowanie z kompilatora F #. Udało mi się znaleźć obejście, ale pierwotne zachowanie zbija mnie z tropu i chciałem sprawdzić, czy ktoś może mi pomóc zrozumieć, co to powoduje.Dlaczego kompilator F # czasami nieprawidłowo generalizuje funkcje?
Funkcja, którą zdefiniowałem jako nietypową, stawała się ogólna, co zakłócało zdolność funkcji do dzielenia stanu między wieloma wywołaniami. I uproszczone mojego przypadków użycia w dół do następujących:
let nextId =
let mutable i = 0
let help (key:obj) =
i <- i + 1
i
help
nextId "a" // returns 1
nextId "b" // also returns 1!!!!
Dlaczego NextID typu „a -> int zamiast obj -> int? Oczywiście uogólnienie jest również odpowiedzialne za błąd, w którym wielokrotnie powraca 1, ale dlaczego w ogóle występuje uogólnienie?
Zauważ, że jeśli I zdefiniować ją bez nazywania funkcji zagnieżdżonych, że działa zgodnie z oczekiwaniami w dawaniu unikalnych identyfikatorów:
let nextId =
let mutable i = 0
fun (key:obj) ->
i <- i + 1
i
nextId "a" // returns 1
nextId "b" // returns 2
ale jeszcze bardziej tajemnicza, z tą definicją, F # Interactive nie może zdecydować, czy NextID jest an (obj -> int) lub ('a -> int). Kiedy pierwszy raz zdefiniować go uzyskać
val NextID: (obj -> int)
ale jeśli po prostu eval
nextId
uzyskać
val, to: (” a -> int)
Co tu się dzieje i dlaczego moja prosta funkcja staje się automatycznie ogólna zeded?