Sie deklarieren eine Funktion split'
und eine Funktion spilt'
. Korrigiere die Tippfehler und du solltest gut gehen!
split' :: RawText -> [SingleWord]
spilt' [] = [] -- the first typo is here
split' xs
| xs == [] = []
| isBlank (head xs) = split' xs
| otherwise = waitForBlank xs : spilt' (tail xs) -- here is the second typo
die Meldung zu erklären, ist es am besten Ihren Code in die beiden unterschiedlichen Funktionen aufteilen Sie erklärt:
split' :: RawText -> [SingleWord]
split' xs
| xs == [] = []
| isBlank (head xs) = split' xs
| otherwise = waitForBlank xs : spilt' (tail xs)
-- spilt' :: [a] -> [a] (or something like this)
spilt' [] = []
Wenn Sie jetzt in split'
Rekursion, rufen Sie spilt'
. Da die von Ihnen deklarierte Funktion spilt'
die nicht leere Liste nicht behandelt, löst sie eine Ausnahme aus.
Auf einer weiteren Notiz, wenn Sie die Tippfehler korrigieren, werden Sie nicht die leere Liste zweimal behandeln müssen:
import Prelude hiding (split)
split :: RawText -> [SingleWord]
split [] = []
split xs
-- | xs == [] = [] this case is matched by the pattern
-- above and thus not needed
| isBlank (head xs) = split' xs
| otherwise = waitForBlank xs : split (tail xs)
Auch wenn Muster auf Listen übereinstimmt, können Sie explizit Mustererkennung gegen die head
und tail
der Liste durch die Faust cons
Anwendung auszuschreiben ausdrücklich:
split [email protected](x:xs)
| isBlank x = split' xs
| otherwise = waitForBlank s : split' xs
Aber irgendwie diese Funktion noch se ems irgendwie klobig, es muss einen besseren Weg geben, alle Buchstaben zu überspringen. Werfen wir einen Blick auf die Bibliotheksfunktionen, um zu sehen, was uns helfen könnte. Sie finden sie here:
-- drops letters from RawText while a certain predicate holds
dropWhile :: (a -> Bool) -> [a] -> [a]
-- takes letters form RawText while a certain predicate holds
takeWhile :: (a -> Bool) -> [a] -> [a]
Diese sehen eher vielversprechend aus. Jetzt können wir waitForBlank
umschreiben als:
waitForBlank xs = takeWhile (not . isBlank) xs
-- or, pointfree:
waitForBlank = takeWhile (not . isBlank)
dropWhile
verwenden, können wir auch machen die split
Funktion effizienter, indem sie alle Nicht-Leerzeichen übersprungen wird. Beachten Sie, dass der Speicherplatz in dem Teil von dropWhile
enthalten ist und explizit gelöscht werden muss.
split :: RawText -> [SingleWord]
split [] = []
split xs = waitForBlank xs : split (dropUntilBlank xs)
-- With dropUntilBlank defined as
dropUntilBlank xs = tail (dropWhile (not . isBlank) xs)
-- without the call of tail, dropUntilBlank would keep the space in between the words:
dropWhile (not . isBlank) "a word" => " word"
-- note the extra space: ^^^
-- using tail on this now produces the correct word:
tail (dropWhile (not . isBlank) "a word") = "word"
Jetzt sieht das Ergebnis schön und sauber:
split :: RawText -> [SingleWord]
split [] = []
split xs = waitForBlank xs : split (dropUntilBlank xs)
waitForBlank xs = takeWhile (not . isBlank) xs
dropUntilBlank xs = tail (dropWhile (not . isBlank) xs)
Der letzte Teil auch mit break
kombiniert werden können:
split :: RawText -> [SingleWord]
split [] = []
split xs = word : split' rest
where
(word, (space:rest)) = break isBlank xs
Diese Antwort geht davon aus, dass alle Wörter durch ein getrennt einzelnes Leerzeichen. Für mehrere Leerzeichen muss dropUntilBlank
neu geschrieben werden, um mehrere Leerzeichen auszuschließen, indem tail
für dropWhile isBlank
ersetzt wird.
Aktivieren Warnungen hier hätte geholfen, die Tippfehler 'spilt' in Spek, Erzeugen einer Nachricht wie„Signatur fehlt für 'spilt'“. – chi