3 Stimmen

Warum verursacht diese Show-Instanz in Haskell (Hugs) einen Stapelüberlauffehler?

Das Folgende ist ein polymorpher Datentyp in Haskell, der von Hugs interpretiert wird. Ich versuche, eine Instanz von Show for Equality zu erstellen.

Die Instanzdeklaration besagt, dass wenn ein Typ "a" in Show ist, dann ist die Gleichheit a in Show. Es sollte die beiden Argumente für den Konstruktor Equals a b in der Form "a = b" ausgeben.

data Equality a = Equals a a 

instance (Show a) => Show (Equality a) where
show (Equals a b) = a ++ " = " ++ b

Wenn Sie jedoch in Hugs etwas wie "(Equality 9 9)" eingeben, erhalten Sie ein Ergebnis:

ERROR - C-Stapelüberlauf

Also habe ich versucht, die Zeile "show (Equals a b)..." mit ein paar Leerzeichen einzurücken. Ich bin mir nicht sicher, was der Unterschied sein würde, aber ich habe nur herumgespielt und dann das hier bekommen:

Inferred type is not general enough
*** Expression    : show
*** Expected type : Show (Equality a) => Equality a -> String
*** Inferred type : Show (Equality [Char]) => Equality [Char] -> String

Kann jemand erklären, warum diese Fehler auftreten, oder einen besseren Weg vorschlagen, diese Show-Instanz zu implementieren?

Ich danke Ihnen!

3voto

Mikhail Glushenkov Punkte 14828

Ihr Code ist falsch eingerückt. Er definiert eine leere Show Instanz:

instance (Show a) => Show (Equality a) where

und eine separate Top-Level-Funktion show :

show (Equals a b) = a ++ " = " ++ b

vom Typ Equality [Char] -> [Char] . Wenn Sie also versuchen, Ihre Show Instanz, die Standard-Definition von show von der Show Klasse abgeholt wird. Schauen Sie sich den Code an:

showsPrec _ x s = show x ++ s
show x          = showsPrec zeroInt x ""

können Sie sehen, dass der Standard show ist definiert als showsPrec , die wiederum definiert ist durch show . Das erklärt, warum Ihr Programm in eine Endlosschleife gerät.

Um den Code zu korrigieren, rücken Sie ihn entsprechend ein und fügen fehlende Aufrufe zu show um den Typfehler zu beheben (der daher rührt, dass man einen beliebigen Typ nicht verketten kann a mit einer Zeichenkette - Sie müssen die a in eine Zeichenkette umwandeln):

data Equality a = Equals a a

instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

Prüfung:

*Main> show (Equals 9 9)
"9 = 9"

1voto

franza Punkte 2236

Ich denke, Ihr Problem liegt darin, dass Sie die Funktion nicht aufgerufen haben show zu den Argumenten ab . Ich habe dies in GHC getan, aber ich denke, es sollte funktionieren:

data Equality a = Equals a a 

instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

Dann:

> Equals 9 9
9 = 9

1voto

Erik Hinton Punkte 1948

Die Einrückung ist wichtig, da Haskell manchmal eine seltsame Empfindlichkeit gegenüber Leerzeichen hat. Ohne den Einzug kann der Compiler nicht erkennen, dass die folgende Anweisung zur where .

Der Fehler, den Sie erhalten, liegt daran, dass der polymorphe Typ, der keine Einschränkungen hat, nicht sicherstellt, dass ab mit der Zeichenkette " = " verkettet werden kann. Was ist, wenn Sie Folgendes haben Equals 1 1 . Wie würden Sie das verketten, ohne die Ints vorher zu Strings zu machen?

Wenn Sie jedoch show a und b zuerst, dann klappt alles, denn show martials die Werte in etwas, das mit einem String verkettet werden kann.

data Equality a = Equals a a

instance (Show a) => Show (Equality a) where
    show (Equals a b) = (show a) ++ " = " ++ (show b)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X