2016-10-04 1 views
4

Guten Abend alle, ich bin neu in Haskell. Ich versuche eine Liste zusammenzufassen, in der Unicode-Werte gelesen und in einer Liste gespeichert werden, und summiere dann die ganzen Zahlen.Wie vermeidet man "Ausnahme: Prelude.head: leere Liste"? - Haskell

getLetterUnicodeValue :: Char -> Int 
getLetterUnicodeValue l = (ord l) - 64 

unicodeValueList :: String -> [Int] 
unicodeValueList x = getLetterUnicodeValue (head x) : unicodeValueList (tail x) 

total :: [Int] -> Int 
total []  = 0 
total x = (head x) + (total (tail x)) 

habe ich den Fehler, leere Liste, wenn die Zeichenfolge auf das letzte Zeichen und die Summe up-Funktion kommen kann nicht erfolgreich ausführen. Gibt es eine Möglichkeit, die Funktion unicodeValueList zu stoppen, wenn es zu seinem Ende kommt.

*** Exception: Prelude.head: empty list 
+7

Ja es gibt, * und Sie haben es bereits für 'total' * getan ... – immibis

Antwort

5

Der sicherste Weg, diese Ausnahme zu vermeiden, ist die Verwendung von head. Stattdessen können Sie Pattern-Matching verwenden Sie den Kopf und Schwanz einer Liste zu erhalten:

unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs 

total (x:xs) = x + total xs 

Auf diese Weise x und xs ist nur verfügbar, wenn die Liste nicht leer ist, und es ist sichergestellt, dass Sie nicht versehentlich den Kopf zugreifen oder Schwanz einer leeren Liste.

Natürlich erhalten Sie jetzt eine Warnung, dass die Musterübereinstimmung unvollständig ist: Sie geben nicht an, was passieren soll, wenn die Liste leer ist. Natürlich war das vorher auch so, aber jetzt, da Sie den Mustervergleich verwenden, kann der Compiler das tatsächlich sehen und Sie davor warnen (während der vorherige Code zur Laufzeit ohne vorherige Warnung abgestürzt ist).

Was sollte also getan werden, wenn die Liste leer ist? Nun, eine leere Zeichenfolge enthält keine Unicode-Werte, oder? So sollte es die leere Liste zurück, wenn die Eingabe leer ist:

unicodeValueList [] = [] 

Natürlich kann man nicht Notwendigkeit Muster für Ihre Fehler zu beheben. Sie könnten einfach eine if verwenden, um sicherzustellen, dass Sie nur head und tail aufrufen, wenn die Liste nicht leer ist. Aber wenn Sie das tun, wird der Compiler nicht in der Lage sein zu überprüfen, dass Ihre Überprüfungen in Ordnung sind. Wenn Sie Mustervergleiche verwenden und die unsicheren Funktionen head und tail vollständig umgehen, können Sie nie versehentlich auf den Anfang oder das Ende einer leeren Liste zugreifen, und der Compiler warnt Sie, wenn Sie vergessen, dass die Liste möglicherweise leer ist .

2

Ja, Sie werden nur zu Mustererkennung haben in unicodeValueList

unicodeValueList :: String -> [Int] 
unicodeValueList [] = [] 
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs 

Hinweis dies mehr schön als unicodeValueList = map getLetterUnicodeValue geschrieben werden konnte. Der Grund für den Fehler head ist, dass Ihre Rekursion keinen Basisfall hatte - sie versucht immer wieder zu rekrutieren, selbst wenn sie die leere Liste erreicht hat.

+0

Es funktioniert, vielen Dank! –

Verwandte Themen