2016-04-29 6 views
0

Zuerst den folgenden Code prüfen, die die Anzahl der Leerzeichen in einem String zählt:mit Liste Patterns Vergleich

countSpaces :: String -> Int 
countSpaces [] = 0 
countSpaces (c : restOfString) 
    = d + countSpaces restOfString 
     where d = if c == ’ ’ then 1 
          else 0 

Hier ist meine Fragen:

1, wenn ich einen Anruf zu tätigen: countSpaces "abc", Was passiert dann, wenn diese Funktion versucht, die Zeichenfolge "abc" mit (c: restOfString) zu verknüpfen. Ich meine, restOfString ist: "abc" in diesem Anruf aber was ist (c:restOfString)? Sie "consing" etwas (die Variable? c) zu restOfstring und dann versuchen Sie zu entsprechen? Ich verstehe es einfach nicht.

2, ich versuche, den Code auszuführen, aber ich bekomme einen Parse-Fehler warum?

Parse-Fehler bei der Eingabe ‚'‘

3, wird dieser Funktionsaufruf countSpaces ins Unendliche? seit restOfString ist immer gleich und nicht reduziert, z. Der Anruf countSpaces "aaa" wird nicht nach dem ersten Anruf, zweite oder einen Anruf ändern, nicht wahr?

  • hinzugefügt danach *

nun diesen Code betrachten, die die gleiche Aufgabe erfüllt:

countSpaces :: String -> Int 
countSpaces [] = 0 
countSpaces (’ ’ : restOfString) 
     = 1 + countSpaces restOfString 
countSpaces (_ : restOfString) 
     = 0 + countSpaces restOfString 

1, so dass, wenn wir versuchen, (’ ’ : restOfString) einen Anruf countSpaces "abc" das Muster zu machen, wird nur immer größer da jedes mal countSpaces aufgerufen wird, wird dies nur eine ' ' zu restOfString, es sei denn, jedes Mal countSpaces wird die erste ch aufgerufen werden ar in der Zeichenfolge wird geändert in: ' '. so in dem ersten Aufruf von countSpaces "abc" dann (’ ’ : restOfString) ist ' ':"bc", was verwirrend ist richtig, da es "a" mit einem leeren statt consing ersetzt es so, dass wir bekommen: " abc"

+0

'" abc "' ist nur syntaktischer Zucker für '['a', 'b', 'c']' oder ''a': 'b': 'c': []'. – chepner

+1

Sie verwenden seltsame Apostrophe. Vergleiche das: '' 'mit deinem,' ''. Sie sind verschiedene Charaktere. – Arnon

Antwort

6

1, wenn ich einen Anruf zu tätigen: countSpaces "abc", was passiert dann, wenn diese Funktion versucht, die Zeichenkette "abc" mit: (c: restOfString) abzugleichen.

Wenn Sie dieses Muster Operator auf der linken Seite von : mit der Nachteile entsprechen :, das Element ist das erste Element in der Liste, und auf der rechten Seite von : ist der Rest der Liste. Die folgenden sind äquivalent:

"abc" == 'a' : "bc" 

Da ein String ist eine Liste von Zeichen (insbesondere [Char]) konnte die oben auch geschrieben werden:

"abc" == 'a' : 'b' : 'c' : [] 

2, versuche ich das laufen Code, aber ich bekomme einen Parse-Fehler warum?

Ihr Analysefehler ist, weil Sie das falsche Zeichen für ein einfaches Anführungszeichen verwenden.Sie verwenden unicode 0x2019, wenn Sie das, wird countSpaces bis ins Unendliche diese Funktion aufrufen ASCII/Unicode Apostrophe character: '

3 verwendet werden sollte?

Es zählt nur bis unendlich, wenn Ihre Zeichenfolge unendlich ist. Die Reduktion geschieht eigentlich in diesem Teil:

countSpaces restOfString 

Um zu verstehen, warum, siehe meine Antwort für einen Teil 1. Im Fall von „abc“, restOfString ist „bc“.

4, so dass, wenn wir versuchen, einen Anruf countSpaces „abc“ das Muster zu machen: (‚‚: restOfString) wird wird nur immer größer, da jedes Mal countSpaces dies genannt wird ein gerechter cons‘‘ zu restOfString, jeder Es sei denn, time countSpaces werden aufgerufen, dann wird das erste Zeichen in der Zeichenfolge geändert in: ''. also im ersten Aufruf von countSpaces "abc" dann ('': restOfString) ist '': "bc", was ist verwirrend oder?

Ich denke, dass Ihre Verwirrung von der Tatsache herrührt, dass Mustererkennung und Aufbau einer Liste identisch aussehen. Was passiert, wenn Sie (' ':restOfString) schreiben, hängt vollständig vom Kontext ab.

Sie von einer Funktionsdefinition denken kann als in zwei Teile durch die = Zeichen getrennt aufgebrochen werden:

countSpaces (' ' : restOfString) = 1 + countSpaces restOfString 
^       ^^^      ^
|        | | |       | 
-------------------------------- | ---------------------------- 
       |     |     | 
     Pattern Matching  Separator  Function Body 

der Musterteil Passende nicht den Ausgang beeinflussen. Wenn Sie (' ' : restOfString) auf der Pattern-Matching-Seite verwenden, sagen Sie: "Wenn der in die countSpaces-Funktion übergebene Parameter mit einem Leerzeichen beginnt, geben Sie zurück, was in diesem Funktionskörper ist. Wenn das erste Zeichen kein Leerzeichen ist, versuchen Sie den nächsten Muster definiert ". In beiden Fällen (unabhängig davon, ob eine Übereinstimmung besteht oder nicht) wird der in countSpaces übergebene Wert in keiner Weise verändert (es wird kein Leerzeichen vorangestellt; dies passiert nur im Funktionskörper).

Umgekehrt, wenn Sie (' ' : restOfString) in der Funktion Body setzen, sagen Sie "geben Sie den restOfString Wert mit einem vorangestellten Leerzeichen".

+0

Ok, hier ist was mich verwirrt: Wenn wir ändern würden: c zu 'c' würde das bedeuten, dass Sie das erste Element in RestOfList zu 'c' ändern würden? aber ("c": "ab") würde "cab" produzieren. Das Ergebnis unterscheidet sich, wenn es sich um einen Parameter (wie in dieser Funktion) oder um einen String handelt (der kein Parameter für einen Aufruf ist) @Chad Gilberg –

+0

'('c':" ab ")' im Zusammenhang mit dem Mustervergleich wird * nur * passt immer zum String "cab". Wenn Sie stattdessen _returning_ '('c':" ab ")' angeben, geben Sie die Zeichenfolge "cab" zurück. Denken Sie daran, dass "c" ein Variablenname ist und "c" ein "Char" ist, da es von einfachen Anführungszeichen umgeben ist. –

+0

'countSpaces ('': restOfString) = 1 + countSpaces restOfString' und ' countSpaces (_: restOfString) = 0 + countSpaces restOfString' sind gültige Möglichkeiten, das Problem durch Mustererkennung zu lösen. –