2017-10-08 4 views
2

Also habe ich diese Funktion, um mir die "n" ersten Elemente aus einer Liste "(b: bs);Nicht erschöpfende Muster in der Funktion take6 error?

1 module Sexta where 
2 
3 take6::Int->[a]->[a] 
4 take6 n (b:bs) = if n<=0 then [] 
5     else [b] ++ (take6 (n-1) bs) 

Das Problem, das ist, wenn ich versuche: take6 2 [], es zeigt:

*** Exception: sexta.hs:(4,1)-(6,15): Non-exhaustive patterns in function take6 

ich nicht, warum, cuz, wenn ich versuchen, diese von Hand.

take6 2 [] 
    = [] ++take6 1 [] 
    = [] ++[]++take6 0 [] 
    = [] ++[]++[] 
    = [] 

Antwort

3

In Ihrem Programm, das Sie schreiben:

take6 n (b:bs) = ... 

Aber hier gibt es also ein Muster (b:bs) verwenden, die die „Nachteile“ Konstruktor der Liste ist. Der Konstruktor nimmt einen Kopf b und einen Schwanz bs. Der Listentyp hat jedoch zwei Konstruktoren: die "Cons", die wir bereits hier besprochen haben, und die leere Liste []. Haskell beschwert sich, dass es keine Klausel für das leere Listenmuster des zweiten Arguments finden kann. Also muss Ihre Funktion mit einer Form definiert werden:

take6 n [] = ... 
take6 n (b:bs) = ... 

Jetzt ist noch die Frage, was man hier machen soll. Unabhängig davon, was wir im Falle einer leeren Liste nehmen, können wir keine Elemente emittieren mehr, so dass Sie wahrscheinlich die leere Liste zurückkehren möchten, so:

take6 _ [] = [] 

weiterhin machen Sie in der Tat einen Unterschied zwischen n weniger als oder gleich Null ist in diesem Fall ist das Ergebnis eine leere Liste:

take6 n (b:bs) | n <= 0 = [] 

aber es gibt auch einen Fall, in dem n > 0. In diesem Fall wollen wir tatsächlich b dem voranstellen. Kümmern Sie jedoch, dass eine effizientere Art und Weise vorangestellt wird, wieder mit dem „cons“ Konstruktor:

oder in voller Länge:

take6 :: Int -> [a] -> [a] 
take6 _ [] = [] 
take6 n (b:bs) | n <= 0 = [] 
       | otherwise = b : take6 (n-1) bs 
+0

Ja, es ist möglicherweise effizienter. Wenn GHC jedoch mit aktivierten Optimierungen ausgeführt wird, sollten sie identisch sein. Ich habe dieses Beispiel nicht überprüft, aber es gibt spezielle Regeln, um Literallisten in 'Build'-Formen zu entzippen, die mit der' foldr'-Form in '(++)' verschmelzen sollten. In diesem Fall hat es keinen Sinn, sich auf diese Optimierung zu verlassen, aber ich vermute, dass es wichtiger ist, wenn man '[a]' als das Monoid-Ziel einer 'FoldMap' verwendet. – dfeuer

2

Das Muster b:bs nicht die leere Liste übereinstimmen, die Sie über einen separaten Fall ha müssen Legen Sie die leere Liste fest.

2

Sie destrukturieren die Liste, bevor Sie n überprüfen, also selbst wenn es 0 ist, müssen Sie die Liste nicht leer sein. Sie könnten einen Wächter verwenden, um diesen Fall zu behandeln, aber das würde in diesem Fall nicht helfen, wenn die Liste zu kurz ist.

Verwandte Themen