2017-10-08 3 views
2

donc j'ai créé cette fonction, pour me donner les "n" premiers éléments d'une liste, "(b: bs);Motifs non exhaustifs dans l'erreur de la fonction take6?

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) 

Le problème est que lorsque je tente: take6 2 [], il montre:

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

pourquoi je ne, cuz quand je tente cette main.

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

Répondre

3

Dans votre programme, vous écrivez:

take6 n (b:bs) = ... 

Mais ici, vous utilisez donc un modèle (b:bs) qui est le constructeur des « contre » de la liste. Le contre constructeur prend une tête b et une queue bs. Le type de liste a cependant deux constructeurs: le "contre" dont nous avons déjà parlé ici, et la liste vide []. Haskell se plaint de ne pas trouver de clause pour le modèle de liste vide du deuxième argument. Donc, votre fonction doit être définie avec une forme:

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

Maintenant, la question est encore de savoir quoi faire ici. Peu importe ce que nous prenons dans le cas d'une liste vide, nous ne pouvons émettre des éléments plus, vous voulez probablement retourner la liste vide, donc:

take6 _ [] = [] 

En outre, vous permettent en effet une distinction entre n étant inférieure ou égal à zéro dans ce cas, le résultat est une liste vide:

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

, mais il y a aussi un cas où n > 0. Dans ce cas, nous voulons en effet préfixer b au take6 (n-1) bs. L'esprit cependant que d'une manière plus efficace de préfixer, est de nouveau à l'aide du constructeur « cons »:

ou en totalité:

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

Oui, ce peut-être plus efficace. Mais lorsque GHC est exécuté avec des optimisations activées, elles doivent être identiques. Je n'ai pas vérifié cet exemple, mais il existe des règles spéciales pour désosser des listes littérales dans des formes 'build' qui devraient fusionner avec la forme' foldr' dans '(++)'. Dans ce cas, il ne sert à rien de se fier à cette optimisation, mais je soupçonne qu'il est plus important d'utiliser '[a]' comme cible monoid d'un foldMap. – dfeuer

2

le modèle b:bs ne correspond pas à la liste vide Vous avez besoin d'un cas distinct ha voir la liste vide.

2

Vous êtes en train de déstructurer la liste avant de cocher n, donc même si c'est 0 vous avez besoin que la liste soit non vide. Vous pourriez utiliser un garde pour gérer ce cas, mais cela n'aiderait pas dans ce cas où la liste est trop courte.