Bitte erklären Sie mir die Monomorphie-Beschränkung?

8

Ich begann mit 99 Haskell-Problemen und ich war auf Problem 7 und meinen Unittests explodierten.

Anscheinend liegt das daran: Ссылка

Ich wollte nur sichergehen, dass ich das richtig verstanden habe, weil ich irgendwie verwirrt bin.

Situation 1: func a wird ohne Typ def oder mit einem nicht strikten Typ def definiert und dann einmal verwendet. Der Compiler hat keine Probleme, den Typ zur Kompilierzeit abzuleiten.

Situation 2: das gleiche func a wird oft im Programm verwendet, der Compiler kann nicht zu 100% sicher sein, was der Typ ist, wenn er die Funktion für die gegebenen Argumente nicht erneut berechnet.

Um den Rechenverlust zu vermeiden, beschwert sich ghc beim Programmierer, dass es einen strikten Typ def benötigt a um richtig zu funktionieren.

Ich denke, in meiner Situation hat assertEqual den Typ def von

%Vor%

Ich bekam einen Fehler, als test3 definiert wurde, was ich interpretierte, dass es 2 mögliche Typen für die Rückgabe von testcase3 (Show und Eq) gab und nicht wusste, wie ich weitermachen soll.

Klingt das richtig oder bin ich komplett ausgeschaltet?

problem7.hs:

%Vor%

1. Situation: testcase3 = flatten (List [])

%Vor%

Zweite Situation: testcase3 = flatten (List []) :: Eq a => [a]

%Vor%     
user1561402 29.07.2012, 19:14
quelle

1 Antwort

4

Es ist nicht so sehr die Monomorphie-Einschränkung, es ist die Auflösung von mehrdeutigen Variablen durch säumig , die den Kompilierungsfehler verursacht.

%Vor%

flatten erzwingt keine Einschränkungen für die Typvariable a , es gibt also kein Problem mit der Definition von testcase3 als solcher, es wäre polymorph.

Aber wenn Sie es in test3 verwenden,

%Vor%

Sie erben die Einschränkungen von

%Vor%

Nun muss der Compiler herausfinden, an welchem ​​Typ testcase3 verwendet werden soll. Es gibt nicht genügend Kontext, um den Typ zu bestimmen, daher versucht der Compiler standardmäßig, die Typvariable aufzulösen. Gemäß den Standardregeln kann ein Kontext (Eq a, Show a) nicht standardmäßig aufgelöst werden , da nur Kontexte berücksichtigt werden können, die mindestens eine numerische Klasse enthalten. Daher schlägt die Kompilierung aufgrund einer mehrdeutigen Variablen fehl.

testcase3' und testcase3'' fallen jedoch aufgrund der Signatur des Ausdruckstyps unter die Monomorphie-Einschränkung, die der rechten Seite der Definition Beschränkungen auferlegt, die von der linken geerbt werden.

testcase3' kann daher nicht kompiliert werden, unabhängig davon, ob es in einer Assertion verwendet wird.

testcase3'' wird standardmäßig auf [Integer] zurückgesetzt, da die Signatur des Ausdruckstyps eine numerische Einschränkung auferlegt. Wenn der Typ für testcase'' monomorphisiert wird, wird daher die Variable des eingeschränkten Typs standardmäßig auf Integer gesetzt. Dann ist der Typ, in dem es in test3 verwendet wird, keine Frage.

Wenn Sie den Bindungen Typensignaturen anstatt auf der rechten Seite gegeben hätten,

%Vor%

beide Werte hätten sich selbst zu polymorphen Werten kompiliert, aber immer noch wäre nur testcase3'' in test3 verwendbar, da nur dadurch die erforderliche numerische Integritätsbedingung eingeführt wird, um Standardwerte zuzulassen.

    
Daniel Fischer 29.07.2012, 19:42
quelle