2010-04-20 17 views
5

Erklären Wie ML die Typinferenz in der folgenden Funktionsdefinition durchführen:ML Typinferenz auf einen C++ Programmierer

let add a b = a + b 

Ist es wie C++ Vorlagen, wo keine Typüberprüfung bis zum Zeitpunkt der Vorlage Instanziierung ausgeführt wird, nachdem Wenn der Typ die erforderlichen Operationen unterstützt, funktioniert die Funktion oder wird ein Kompilierungsfehler ausgelöst?

also beispielsweise die folgende Funktion Vorlage

template <typename NumType> 
NumType add(NumType a, NumType b) { 
    return a + b; 
} 

für Arbeit

add<int>(23, 11); 

aber für nicht

add<ostream>(cout, fout); 

Arbeit ist, was ich vermute, richtig ist oder ML-Inferenz funktioniert anders?

PS: Entschuldigung für mein schlechtes Englisch; Es ist nicht meine Muttersprache.

+1

Fragen Sie nach Typ-Inferenz oder Typprüfung? – sepp2k

+0

Inferenz. Welche Arten von Typen werden aus der ML-Funktionsdefinition in meinem Beispiel abgeleitet? –

Antwort

5

Ich schlage vor, Sie einen Blick auf diesen Artikel haben: What is Hindley-Milner? (and why is it cool)

Hier ist das einfachste Beispiel verwenden sie Typinferenz zu erklären (es ist nicht ML, aber die Idee ist die gleiche):

def foo(s: String) = s.length 
// note: no explicit types 
def bar(x, y) = foo(x) + y 

Betrachten wir einfach die Definition von bar, können wir leicht sehen, dass sein Typ sein muss (String, Int) => Int. Das ist eine Art Schlussfolgerung auf den Punkt gebracht. Lesen Sie den ganzen Artikel für weitere Informationen und Beispiele.

Ich bin kein C++ - Experte, aber ich denke, Vorlagen sind etwas anderes, das näher an Generizität/Parametrik ist, was etwas anderes ist.

+0

Was ich nicht verstehe ist, warum der Typ von 'a' und' b' in 'fun func (a, b) = a + b' zum Beispiel nicht auf' real' (Gleitkomma) zurückgeführt wird. Ist das so, weil 'int' Vorrang vor' real' hat? – ZhekaKozlov

4

ML verwendet Hindley-Milner type inference. In diesem einfachen Fall muss man nur den Körper der Funktion betrachten und sehen, dass er + mit den Argumenten verwendet und das zurückgibt. Somit kann er folgern, dass die Argumente der Typ der Argumente sein müssen, die + akzeptiert (d. H. Ints), und die Funktion gibt den Typ zurück, der + zurückgibt (auch int). Somit ist der gefolgerte Typ von addint -> int -> int.

Beachten Sie, dass in SML (aber CAML nicht) + auch für andere Typen als int definiert ist, aber es wird immer noch int schließen, wenn es mehrere Möglichkeiten sind (dh die add Funktion, die Sie nicht verwendet werden, definiert sind, können zwei Schwimmern hinzufügen) .

5

Ich denke, versuchen ML-Inferenz auf fast alles in C++ zu beziehen ist eher zu Verwirrung führen als Verständnis. C++ hat einfach nichts, was ähnlich wie Typinferenz ist.

Der einzige Teil von C++, der die Typisierung nicht explizit macht, sind Templates, aber (meistens) unterstützen sie generische Programmierung. Eine C++ - Funktionsvorlage, wie Sie sie angegeben haben, könnte gleichermaßen für eine unbegrenzte Menge von Typen gelten - zum Beispiel für den Code, den Sie als Template-Parameter NumType verwenden, aber mit Strings arbeiten würde. Ein einzelnes Programm könnte Ihre add instanziieren, um zwei Zeichenfolgen an einer Stelle und zwei Zahlen an einer anderen Stelle hinzuzufügen.

ML-Inferenz ist nicht für generische Programmierung.In C oder C++ definieren Sie explizit den Typ eines Parameters, und der Compiler prüft dann, ob alles, was Sie mit diesem Parameter versuchen, von diesem Typ zugelassen wird. ML kehrt das um: es schaut sich die Dinge an, die Sie mit dem Parameter machen, und ermittelt, was der Typ für Sie haben muss, um diese Dinge tun zu können. Wenn Sie versucht haben, Dinge zu tun, die sich widersprechen, wird es Ihnen sagen, dass es keinen Typ gibt, der die Einschränkungen erfüllen kann.

Dies wäre in C oder C++ ziemlich unmöglich, vor allem wegen der impliziten Typkonvertierungen, die erlaubt sind. Nur zum Beispiel, wenn ich etwas wie a + b in ML habe, kann es sofort schließen, dass a und b ints sein müssen - aber in C oder C++ könnten sie fast jede Kombination von Ganzzahl oder Zeiger oder Fließkommatypen sein (mit der Einschränkung dass sie nicht sowohl Zeiger sein können) oder definierte Typen verwenden, die operator+ überlasten (zB std::string). In ML kann das Finden von Typen im schlimmsten Fall exponentiell sein, ist aber fast immer ziemlich schnell. In C++ würde ich schätzen, dass es viel häufiger exponentiell ist, und in vielen Fällen würde es wahrscheinlich unterbestimmt sein, so dass eine gegebene Funktion irgendeine von verschiedenen Signaturen haben könnte.

+2

C++ 0x hat eine lokale Inferenz (wie C# aber etwas allgemeiner) mit dem Schlüsselwort 'auto'. Aber das ist natürlich weit entfernt von Hindley-Milner. Grundsätzlich funktioniert es nur zum Zeitpunkt der Deklaration und nur dann, wenn die Variable sofort mit einem konstanten Ausdruck initialisiert wird. –