2011-02-03 4 views
2

Impossible de comprendre pourquoi la correspondance de motif ne fonctionne pas! Je commence par Hasklell, alors soyez patient!Pourquoi j'obtiens "Exception: Prelude.head: liste vide"?

-- matrix implemented as a list of lists (rows of the matrix) 
test_matrix3 = [[1,0,0],[2,-3,0],[4,5,6]] 

-- transpose of a given matrix 
transpose (x:[]) = [x] 
transpose [email protected](x:_) = map head all : transpose ([tail y | y <- all]) 

exécution:

*Main> transpose test_matrix3 
[[1,2,4],[0,-3,5],[0,0,6],[*** Exception: Prelude.head: empty list 

Répondre

2

Celui-ci a fonctionné pour moi:

transpose' ([]:_) = [] 
transpose' xs = (map head xs) : (transpose' (map tail xs)) 

Test:

*Main> transpose' test_matrix3 
[[1,2,4],[0,-3,5],[0,0,6]] 
+0

Ici, la première clause est consciente que le premier élément est une liste vide, il suppose que les éléments restants sont également des listes vides. La deuxième clause peut être réécrite comme juste transposer xs = map head xs: (transposer '$ map tail xs) '. –

+1

Je viens de modifier mon exemple entourant transposer l'appel récursif avec des parenthèses et ** ça marche **. Je suis un peu confus! ** Pourquoi ** ce comportement? EDIT: faux, fonctionne également sans parenthèses – gremo

+0

Le dernier appel à 'transposer 'est' transpose' [[], [], []] ', il correspond à la première liste, et ignore la liste de repos, qui est' [[], []] '. –

1

Considérez que vous travaillez sur une liste-des-listes. Par conséquent, votre première correspondance de modèle échoue toujours sur votre matrice de test. Fondamentalement, vous continuez à prendre la queue de chaque élément de votre liste, mais cela ne réduit pas le nombre d'éléments dans votre liste, cela réduit simplement leur taille individuelle.

Pour corriger cela, vous pouvez modifier votre premier modèle pour correspondre à la structure de x.

Rappelez-vous, liste-des-listes!

+0

Bien sûr, je l'ai eu. Mais je ne peux pas trouver un bon endroit pour apprendre une sorte de correspondance de motif "avancé". J'ai essayé ([]: _) et ça ne marche pas. Aussi ([], _) ne correspondra qu'à [[], []] ... – gremo

+0

@Gremo: '([], _)' est un tuple et ne correspondra donc qu'à un tuple, dont le premier élément est une liste vide . Essayez, par exemple, d'évaluer 'let ([], _) = [[], []] dans 42', vous obtiendrez une erreur de compilation contrairement, par exemple,' let [[], _ ] = [[], []] dans 666'. –

6
transpose [[1,0,0],[2,-3,0],[4,5,6]] 
= [1,2,4] : transpose [[0,0],[-3,0],[5,6]] 
= [1,2,4] : [0,-3,5] : transpose [[0],[0],[6]] 
= [1,2,4] : [0,-3,5] : [0,0,0] : transpose [[],[],[]] 

Et voici où cela arrive. Cela ne correspond pas au premier modèle, car ce n'est pas une liste singleton - c'est une liste avec trois éléments. Alors:

= [1,2,3] : [0,-3,5] : [0,0,0] : map head [[],[],[]] : transpose (map tail [[],[],[]]) 

Ce qui vous donnera une erreur pour chaque liste vide, puisque ni head ni tail sont définis sur les listes vides.

+0

Très bonne explication, mais je ne comprends pas pourquoi [[], [], []] ne correspond pas au premier. – gremo

+1

@Gremo: Cela correspondrait, s'il n'y aurait qu'une seule liste '[[]]', pas trois '[[], [], []]'. Parce que '(x: [])' supprime le premier élément d'une liste et suppose qu'il n'y a pas d'autres éléments, i. e. '(x: [])' est identique à '([x])', mais vous avez '(x: [[], []])', qui est '[x, [], []]' . –

+0

luqui, vous rock :) – Daniel