2016-11-08 3 views
3

Ich bin ziemlich neu in Haskell und ich versuche, meine eigene Länge Funktion wie folgt zu definieren:Definieren einer Länge Funktion Schwanz mit

lengthz :: [a] -> a lengthz [] = 0 lengthz n = 1 + length (tail n)

Warum kompilieren bedeutet dies nicht? Und oder stimmt etwas mit meiner Logik nicht?

Danke!

+0

Beachten Sie, dass "Schwanz" am besten zu vermeiden ist, da es Ihr Programm zum Absturz bringen kann, wenn Sie die leere Liste übergeben. Sie sollten stattdessen (vollständige) Mustererkennung verwenden, wenn möglich, die nicht das gleiche Problem hat - z. 'längez (x: xs) = 1 + längez xs'. – chi

Antwort

5

Zuerst haben Sie einen Tippfehler in Ihrem rekursiven Aufruf an lengthZ. Dies zu beheben, in denen wir einen neuen Typ Fehler:

No instance for (Num a)

Was wir, dass die Funktion (+), um erzählt zu bedienen ist, wir die typeclass Num als Einschränkung in unserer Typdeklaration enthalten muss. Wir fügen auch eine andere Typvariable für die Elemente der Liste ein, so dass die Funktion auf Listen angewendet werden kann, die Elemente eines beliebigen Typs enthalten. Wir schreiben also die Funktion wie folgt:

lengthz :: Num b => [a] -> b 
lengthz [] = 0 
lengthz n = 1 + lengthz (tail n) 

die nur funktioniert, wie wir erwarten würden:

ghci>> lengthz [1,2,3] 
3 
ghci>> lengthz [] 
0 
+1

Warum nicht 'längez :: Num a => [x] -> a' Sie verwenden den Inhalt der Liste überhaupt nicht. – epsilonhalbe

+0

Eine Einschränkung von 'Integral b' wäre wahrscheinlich besser; Was würde es für eine Liste bedeuten, eine "Länge" von 1,5 zu haben? Lassen Sie den Anrufer bei Bedarf die Länge in einen realen Typ konvertieren (zum Beispiel einen Durchschnitt berechnen). (Zum Beispiel 'genericLengthz = fromIntegral. Length'.) – chepner

+0

@chepner Da unsere Definition uns nicht einmal dazu bringen würde, nicht-integrale Typen zu bekommen, ist das nicht eine ziemlich schlechte Rechtfertigung? Ich verstehe, dass die "Länge" -Prinzip-Funktion auf diese Weise eingeschränkt ist, aber dachte, dass die Leute dies als eine Unannehmlichkeit betrachteten. – mnoronha

3

Der Typ für Ihre lengthz Funktion ist [a] -> a.

Das bedeutet, dass Sie eine Liste von a Dinge nehmen und eine einzelne a Sache zurückgeben. Was wäre, wenn Sie eine Liste von Bool hätten? Sie möchten nicht, dass die Funktion Bool ausgibt. Sie möchten eine Int zurückgegeben werden, unabhängig vom Typ der Sache in der Liste. Die einfachste Lösung wäre, den Typ lengthz zu [a] -> Int zu ändern. Dies besagt, dass das Argument eine Liste von allem sein kann (a ist das alles, [] sagt, es ist eine Liste) und der Rückgabetyp ist ein Int.

Verwandte Themen