/ / Wie vermeidet man "Ausnahme: Prelude.head: leere Liste"? - Haskell - Liste, Haskell

Wie vermeide ich "Ausnahme: Prelude.head: leere Liste"? - Haskell - Liste, Haskell

Guten Abend alle, ich bin neu in Haskell. Ich versuche eine Liste zusammenzufassen, in der ich einen String mit Unicode-Werten lese und sie in einer Liste ablege und dann die ganzen Zahlen summiere.

 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))

Ich habe den Fehler einer leeren Liste bekommen, wenn die Zeichenfolge zum letzten Zeichen kommt und die Summenfunktion nicht erfolgreich ausgeführt werden kann. Gibt es eine Möglichkeit, die Funktion zu stoppen? unicodeValueList wenn es zu seinem Ende kommt.

*** Exception: Prelude.head: empty list

Antworten:

5 für die Antwort № 1

Der sicherste Weg, diese Ausnahme zu vermeiden, ist nicht zu verwenden head. Stattdessen können Sie den Mustervergleich verwenden, um den Kopf und das Ende einer Liste zu erhalten:

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

total (x:xs) = x + total xs

Diesen Weg x und xs wird nur verfügbar sein, wenn die Liste nicht leer ist und es garantiert ist, dass Sie niemals versehentlich auf den Kopf oder das Ende einer leeren Liste zugreifen.

Natürlich wirst du jetzt eine Warnung bekommen, dass dieDie Musterübereinstimmung ist unvollständig: Sie geben nicht an, was geschehen 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 Code stürzte zur Laufzeit ohne vorherige Warnung).

Was sollte also gemacht werden, wenn die Liste leer ist? Nun, eine leere Zeichenfolge enthält keine Unicode-Werte, oder? Daher sollte die leere Liste zurückgegeben werden, wenn die Eingabe leer ist:

unicodeValueList [] = []

Natürlich tust du nicht brauchen Mustererkennung, um Ihren Fehler zu beheben. Du könntest einfach einen benutzen if um sicherzustellen, dass Sie nur anrufen head und tail wenn die Liste nicht leer ist. Aber wenn Sie das tun, wird der Compiler nicht in der Lage sein zu überprüfen, dass Ihre Prüfungen in Ordnung sind. Wenn Sie Mustervergleiche verwenden und die unsicheren vermeiden head und tail funktioniert vollständig, Sie können nie versehentlich auf den Kopf oder das Ende einer leeren Liste zugreifen und der Compiler wird Sie warnen, wenn Sie jemals vergessen, dass die Liste leer ist.


2 für die Antwort № 2

Ja, du musst nur ein Muster erstellen unicodeValueList

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

Beachten Sie, dass dies besser als geschrieben werden könnte unicodeValueList = map getLetterUnicodeValue. Der Grund, warum Sie den Fehler erhalten head ist, dass Ihre Rekursion keinen Basisfall hatte - sie versucht immer wieder zu rekrutieren, selbst wenn sie die leere Liste erreicht hat.