2017-06-11 2 views
1

Ich habe versucht, den folgenden Code funktioniert:Haskell Muster nicht überein [_]

{-# OPTIONS_GHC -fwarn-incomplete-patterns #-} 
import Data.List 
format :: String -> String 
format [] = [] 
format (a:b:xs) 
| a == 'W' && b == 'U' = " " ++ format (drop 1 xs) 
| otherwise = a : format (b:xs) 

songDecoder :: String -> String 
songDecoder xs = unwords. words . format $ xs 

Wenn ich mit Test:

songDecoder "AWUBBWUBC"

I erwarte "ABC" als Ausgabe. Allerdings bin ich ein ungewöhnliches Muster passende Warnung erhalten:

Pattern match(es) are non-exhaustive 
In an equation for ‘format’: Patterns not matched: [_] 

Ich bin nicht sicher, warum ich passen müssen [_], wenn ich

format (a:b:xs) 

Bitte helfen.

+1

Wenn Sie Warnungen mit "-Wall" aktivieren, warnt GHC während der Kompilierung darüber und weist darauf hin, dass der fehlende Fall übereinstimmt. Empfohlen. – chi

Antwort

4

In dem Muster (a:b:xs) passen Sie nur Listen mit der Länge> = 2 an. Ihnen fehlt ein Muster für eine Liste mit einem Artikel.

Zum Beispiel dieses Spiel (a:b:xs):

  1. "AWUBBWUBC" - a ist verpflichtet, "A", b-"W" gebunden ist, und xs ist verpflichtet, "UBBWUBC" (syntaktischer Zucker für 'U':'B':'B':'W':'U':'B':'C':[]).
  2. "AWU" - a und b sind wie oben beschrieben gebunden, aber xs ist jetzt an "W" gebunden.
  3. "AW" - a und b sind wiederum an "A" bzw. "W" gebunden.

So etwas wie "A" würde nicht, weil Sie a-"A" und xs auf die leere Liste binden können, aber Sie haben nichts für b.

Ich hoffe, das erklärt es!

+1

Danke Eric. Ich habe Format hinzugefügt (a: []) = a: [] und es hat funktioniert !! – Amateur

+0

Froh, zu helfen. Genauer gesagt, wie Muster funktionieren. Hoffentlich sind sie dir in zukünftigen Haskell-Kodierungen nützlich! –

4

Wie @EricFulmer schreibt in seiner Antwort, (a:b:xs) entspricht Listen mit zwei oder mehr Elemente. So Ihre Funktion arbeitet wie:

format [] = ...  -- empty list 
format (a:b:xs) = ... -- two or more 

Und Haskell warnt, dass eine Liste mit einem Element [_] wird keine dieser Linien entsprechen: beide Muster scheitern.

Sie sollten daher eine Klausel hinzufügen, um festzulegen, was die Liste ein Element in dem Fall geschehen soll, enthält, zum Beispiel (und wahrscheinlich):

format [email protected][_] = a 

Wo @ ist ein alias Operator und es bindet mit einer Liste mit genau einem Element.

In voller erhalten wir dann:

format :: String -> String 
format [] = [] 
format [email protected][_] = a 
format (a:b:xs) 
| a == 'W' && b == 'U' = " " ++ format (drop 1 xs) 
| otherwise = a : format (b:xs) 

wir die Funktion elegant mehr machen können, um durch die Vergleiche in die Musterabgleich bewegen:

format :: String -> String 
format [] = [] 
format [email protected][_] = a 
format ('W':'U':xs) = format $ drop 1 xs 
format (a:b:xs) = a : format (b:xs) 

nun der letzte Fall kann in vereinfacht werden :

format (a:xs) = a : format xs 

und jetzt die zweite Klausel (unser format [email protected][_]) wird veraltet, da die letzte Klausel auch diesen Fall behandelt. So drehen wir die Funktion in:

format :: String -> String 
format [] = [] 
format ('W':'U':xs) = format $ drop 1 xs 
format (a:xs) = a : format xs 

Ich persönlich denke, dies ist mehr elegant ist, da hier klar ist, was Sie wollen mit dem zweiten Muster übereinstimmen (Sie müssen nicht eine Folge von Bedingungen schreiben). Außerdem kann man fast syntaktisch sehen, dass die Funktion alle möglichen Eingaben verarbeitet.

Verwandte Themen