die Art Fehler Legendes: „erwartete Signatur Int * Int-> Int bekam aber Int * Int-> Int“

StackOverflow https://stackoverflow.com/questions/324612

  •  11-07-2019
  •  | 
  •  

Frage

Die Kommentare zu Steve Yegge 's post über serverseitige Javascript die Vorzüge der Typsysteme in Sprachen und diese Kommentar beschreibt:

  

... Beispiele von HM Stil Systemen, in denen Sie Dinge wie bekommen:

expected signature Int*Int->Int but got Int*Int->Int

Können Sie ein Beispiel für eine Funktionsdefinition geben (oder zwei?) Und einen Funktionsaufruf, der diesen Fehler erzeugen würde? Das sieht aus wie es ziemlich schwierig in einem großen ish Programm zu debuggen sein könnte.

Auch könnte ich habe einen ähnlichen Fehler in Miranda gesehen? (Ich habe es nicht in 15 Jahren verwendet und so meine Erinnerung daran ist vage)

War es hilfreich?

Lösung

Ich würde nehmen Yegge (und Ola Bini) abgegebenen Stellungnahmen auf statische Typisierung mit einem Körnchen Salz. Wenn Sie schätzen, was Sie statische Typisierung gibt, erfahren Sie, wie das Typsystem der Programmiersprache Sie Werke wählen.

IIRC, ML verwendet die '*' Syntax für Tupel. * ist ein Tupel Typ mit zwei Elementen. Also, (1, 2) würde int * int-Typen hat.

Sowohl Haskell und ML Einsatz -> für Funktionen. In ML, int * int -> int würde der Typ einer Funktion sein, die ein Tupel von int und int nimmt und ordnet sie in einem int

.

Einer der Gründe, warum Sie einen Fehler sehen könnte, das vage wie das aussieht Ola zitiert, wenn ML aus einer anderen Sprache kommt, ist, wenn Sie versuchen, und übergeben Sie Argumente Klammern und Kommata, wie würde man in C oder Pascal, zu eine Funktion, die zwei Parameter erwartet.

Das Problem ist, funktionale Sprachen im Allgemeinen Modellfunktionen von mehr als ein Parameter als Funktionen Funktionen der Rückkehr; alle Funktionen übernehmen nur ein einziges Argument. Wenn die Funktion zwei Argumente nehmen sollte, dauert es stattdessen ein Argument und gibt eine Funktion einer einzigen Argument, die das endgültige Ergebnis zurückgibt, und so weiter. Um all diese lesbar, Funktionsanwendung einfach durch Verbindung erfolgt (das heißt die Ausdrücke neben einer Platzierung eines anderen).

Also, eine einfache Funktion in ML (Anmerkung: Ich verwende F # als meine ML) vielleicht ein bisschen wie folgt aussehen:

let f x y = x + y;;

Es hat ein:

val f : int -> int -> int

(A-Funktion für eine ganze Zahl zu nehmen und eine Funktion zurückkehrt, der sich eine ganze Zahl nimmt und gibt eine ganze Zahl ist.)

Wenn Sie jedoch naiv nennen es mit einem Tupel:

f(1, 2)

... Sie werden eine Fehlermeldung erhalten, weil Sie einen int * int etwas erwartet einen int übergeben.

Ich gehe davon aus, dass dies das „Problem“ Ola versucht zu werfen Verleumdungen. Ich glaube nicht, das Problem so schlimm ist, wie er denkt, obwohl; sicher, es ist viel schlimmer in C ++ Vorlagen.

Andere Tipps

Es ist möglich, dass dies in Bezug auf einen schlecht geschriebenen Compiler war die gescheiterten Klammern einfügen Fehlermeldungen eindeutig zu machen. Insbesondere erwartet die Funktion ein Tupel von int und eine int zurückgegeben, aber Sie übergeben ein Tupel von int und eine Funktion von int int. Konkreter (in ML):

fun f g = g (1, 2);

f (42, fn x => x * 2)

Dies wird eine Art Fehler ähnlich den folgenden erzeugen:

  

Erwarteter Typ int * int -> int, bekam Typ int * (int -> int)

Wenn die Klammern weggelassen werden, kann dieser Fehler annoyingly mehrdeutig sein.

Es ist erwähnenswert, dass dieses Problem bei weitem nicht auf Hindley-Milner spezifisch ist. In der Tat kann ich nicht, jede seltsamen Art Fehler die sind spezifisch für H-M. Zumindest keine, wie das Beispiel gegeben. Ich vermute, dass Ola wurde nur bläst Rauch.

Da viele funktionale Sprache können Sie Typnamen in der gleichen Art und Weise erneut zu binden Sie Variablen anbinden können, ist es eigentlich ganz einfach mit einem Fehler wie diese am Ende, vor allem, wenn Sie verwenden etwas generische Namen für die Typen (zB t) in verschiedenen Modulen. Hier ist ein einfaches Beispiel in OCaml:

# let f x = x + 1;;
val f : int -> int = <fun>
# type int = Foo of string;;
type int = Foo of string
# f (Foo "hello");;
This expression has type int but is here used with type int

Was ich hier fertig ist die Typkennung int auf einen neuen Typ rebind, die mit dem eingebauten in int Typ nicht kompatibel ist.

: Mit etwas mehr Aufwand können wir mehr oder weniger die gleichen Fehler wie oben erhalten
# let f g x y = g(x,y) + x + y;;
val f : (int * int -> int) -> int -> int -> int = <fun>
# type int = Foo of int;;
type int = Foo of int
# let h (Foo a, Foo b) = (Foo a);;
val h : int * int -> int = <fun>
# f h;;
This expression has type int * int -> int but is here used with type
  int * int -> int
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top