2017-11-23 2 views
1

Ich habe eine einfache Funktion erstellt, die bei einer Liste eine Liste zurückgibt, in der das zusammenhängende Vorkommen eines Elements in der Eingabe auf eins reduziert wird.Werteinschränkung und Typschlussfolgerung

let rec reduce l = 
match l with 
| []    -> [] 
| [x]    -> [x] 
| x::(y::_ as xs) -> if x = y then 
          reduce xs 
         else 
          x::(reduce xs) 


# reduce [1;1;2;2;2;3;3;4;3;3;3];; 
- : int list = [1;2;3;4;3]. 
# reduce [’a’;’a’;’a’;’b’];; 
- : char list = [’a’; ’b’]. 
# reduce [];;    // The case 
- : ’a list = [] 

Alles wie erwartet, mit Ausnahme der leeren Liste [] Eingang. Der Beschwerdeführer sagt Fehler FS0030: Werteinschränkung. Ich versuchte, ein besseres Verständnis der Phänomene durch die documentation zu bekommen, aber ich habe das Gefühl, dass ich immer noch nicht über die Fähigkeiten verfüge, den Punkt richtig zu verstehen. Warum benötigt eine generische Funktion den Fall, dass [] als Typ angegeben wird? Konnte das Ergebnis [] nicht ohne Typrückschluss gemeldet werden? Und schließlich, wie sollte die Funktion strukturiert sein, um einen solchen Fall zu berücksichtigen?

+0

Das Problem ist, dass '[]' ist '' eine Liste 'aber der Compiler muss herausfinden, was' A' ist und kann nicht –

+0

Vielen Dank @JohnPalmer für Ihren Beitrag. – Worice

Antwort

2

Wie John in dem Kommentar sagte, ist das Problem, dass [] den Compiler keinen Hinweis gibt, was der Typ der Liste ist - in allen anderen Fällen wissen Sie, es ist eine Liste von Zeichen von Ganzzahlen, aber hier, Der Typ ist nicht bekannt.

Sie können keinen F # -Code mit unbekannten generischen Typen ausführen, daher gibt es keine Möglichkeit, Ihren Code auszuführen und eine generische Liste zurückzuerhalten - beim Ausführen von Code müssen alle Typen vollständig angegeben werden.

Sie eine Typanmerkung in einer Reihe von Möglichkeiten zur Verfügung stellen kann, die Art zu beheben:

reduce ([] : int list) 
(reduce [] : int list) 
(reduce:int list -> _) [] 

Sie den Anruf auch in einer anderen generische Funktion wickeln könnte, die, weil jetzt der allgemeine Code kompiliert in einer anderen generisch

let foo() = reduce [] 

Sie haben aber jetzt das gleiche Problem - Sie müssen Typen angeben, wenn foo Aufruf, oder der Compiler muss in der Lage sein, um es aus dem Kontext zu schließen, zum Beispiel: Funktion, die eine Art benötigt, um zu verwenden Wenn Sie schreiben 1 :: foo()

+0

Danke Tomas. Wegen Ihrer einfachen Erklärung habe ich jetzt ein besseres Verständnis für das Problem. – Worice