2

My Custom Art ist:Mustervergleich auf benutzerdefinierten Konstrukteuren Haskell

data Tree a = Leaf a | Node [Tree a] deriving (Show, Eq) 

ich eine Funktion

foo :: Eq a => a -> Tree a -> [Tree a] 

Beispiel

foo 3 (Node [Leaf 1, Leaf 3, Node [Leaf 5, Leaf 3, Leaf 6], Leaf 4, Leaf 3, Leaf 44, Leaf 3]) 

-- this should print [Node [leaf 5, leaf 3, leaf 6], leaf 6, leaf 44] i.e - all elements that follow a "Leaf 3" in the Tree 

Mein Code schreiben müssen wie folgt (unter Verwendung von Muster passend)

foo n (Leaf _) = [] 

foo n (Node (Node z):y:xs) = if length (Node z):y:xs < 2 then [] 
       else (foo n (Node z)):(foo n y:xs) 

foo n (Node (Leaf z):y:xs) = if length (Leaf z):y:xs < 2 then [] 
       else if Leaf n == Leaf z then [y]:(foo n y:xs) 
       else (foo n y:xs) 

Allerdings bekomme ich einen Fehler:

• Couldn't match expected type ‘Tree a’ with actual type ‘[Tree a]’ 

• In the pattern: Node (Node z) : y : xs 

Aber das Muster Node (Node z) : y : xs den Eingang

Node [Node [Leaf 4, Leaf 2], Leaf 6, Leaf 9, Leaf 1] 

Bin ich sagen, dass falsch darstellen könnte? Es scheint perfekt für mich.

Warum schlägt die Mustererkennung fehl?

+2

'Knoten (Node z)' wird zuerst ausgewertet, da es Funktionsanwendung ist, aber es kann nicht beurteilen, weil der erste 'Knoten' erwartet einen' [Baum] ', aber er empfängt etwas, was ein' Baum' zu sein scheint. Probiere 'Knoten (Knoten z: y: xs)'. (In ähnlicher Weise symbolisieren '_: _: _' s in der Folge). – kuoytfouy

+1

Ich kann mehrere Code-Gerüche über den falschen Klammern erkennen. Die Liste '(Leaf z): y: xs' hat sicherlich die Länge> = 2, also sieht das Testen falsch aus. Der Test 'Leaf n == Leaf z' ist seltsam, warum nicht' n == z'? Im Allgemeinen ist die Verwendung von "length" oft der falsche Weg: Der Musterabgleich gibt uns bereits Informationen über die Listenlänge. – chi

Antwort

1

Ich habe ein Beispiel auf repl.it eingerichtet, aber der Code ist unten.

Die erste Sache, die ich tat, war, der Funktion eine konkretere Unterschrift hinzuzufügen, damit es einfacher war, darüber nachzudenken. Fühlen Sie sich frei, es wieder zu Ihrer Originalsignatur zu ändern, sobald Sie alles durchgearbeitet haben. Es ist einfacher, sich vom Konkreten zum Abstrakten zu bewegen, als umgekehrt.

  • Das erste Problem ist ein Mangel an Klammern im Muster war (bedeutete dies, dass statt Tree a, Sie gegen [Tree a] anzupassen versuchten Das ursprüngliche (Node (Node z):y:xs) wie folgt bewertet:.. ((Node (Node z)):y:xs) ich die [email protected]bei Muster hinzugefügt unten für meine eigene Bequemlichkeit, aber Sie können die zu ersetzen, ist es nicht wesentlich ist.
  • Das zweite Problem war, dass man wirklich ein [Tree a] in ein Tree a, Marmelade versucht, weil das ist, was y:xs in foo n y:xs bedeutet, so dass ich ersetzen es durch Node (y:xs) das ist ein Tree a.
  • Das dritte Problem war, dass die Mustererkennung für foo nicht erschöpfend war, am Ende einen Catch-All hinzugefügt, Sie wollen Ihr beabsichtigtes Verhalten betrachten und das aufräumen.

Der Code folgt:

module Main where 

data Tree a = Leaf a | Node [Tree a] deriving (Show, Eq) 

foo :: Int -> Tree Int -> [Tree Int] 
foo n (Leaf _) = [] 

foo n (Node [email protected]((Node z):xs)) = if length all < 2 then [] 
      else (foo n (Node z)) ++ (foo n (Node xs)) 

foo n (Node [email protected]((Leaf z):y:xs)) = if length all < 2 then [] 
      else if Leaf n == Leaf z then [y] ++ (foo n (Node (y:xs))) 
      else (foo n (Node (y:xs))) 
foo _ _ = [] 

myTree :: Tree Int 
myTree = Node [Leaf 1, Leaf 3, Node [Leaf 5, Leaf 3, Leaf 6], Leaf 4, Leaf 3, Leaf 44, Leaf 3] 


main :: IO() 
main = do 
    print (foo 3 myTree) 

Ausgang:

[Node [Leaf 5,Leaf 3,Leaf 6],Leaf 6,Leaf 44]