2009-10-07 4 views
2

j'ai écrit le code suivant dans Haskell pour calculer le produit scalaire de deux vecteurs, mais ne peut pas le compiler en raison de l'erreur suivante:Pourquoi Haskell lance-t-il une erreur «impossible de construire un type infini»?

cannot construct infinite type: a = [a] When generalising the type(s) for dot'

dot :: (Num a) => [a] -> [a] -> a 

[] `dot` [] = 0 
[email protected][xi,xs] `dot` [email protected][yi,ys] = xi*yi + (xs `dot` ys) 

J'ai pris un coup d'œil à this question à l'avance à titre indicatif. Autant que je sache, les types sont corrects. x, y et les deux [] sont des listes, et la fonction renvoie un nombre.

Qu'est-ce qui ne va pas?

+2

C'est l'équivalent de Haskell de référence d'objet non défini ou de débordement de pile, vous allez le voir beaucoup;) –

Répondre

7

Vous confondez la syntaxe d'une liste à deux éléments [x, y] avec la syntaxe pour diviser une liste dans le premier élément et le reste de la liste (x:y). Essayez ceci:

dot :: (Num a) => [a] -> [a] -> a 

[] `dot` [] = 0 
[email protected](xi:xs) `dot` [email protected](yi:ys) = xi*yi + (xs `dot` ys) 

Les modèles @ sont également inutiles, d'ailleurs.

+0

Merci beaucoup, cela a fait l'affaire. – Zaid

8

Ganesh' answer est sur place. Permettez-moi d'expliquer brièvement la signification d'un "type infini".

dot a cette définition de type:

dot :: (Num a) => [a] -> [a] -> a 

Cela signifie que dot prend deux listes de Num éléments et retourne un Num. Votre définition inclut cette ligne:

[email protected][xi,xs] `dot` [email protected][yi,ys] = xi*yi + (xs `dot` ys) 

Depuis, comme le souligne Ganesh sur, [xi,xs] est une liste composée de deux éléments, xi et xs devrait être Num s. Idem pour yi et ys. Mais ils sont passés comme arguments à dot:

xs `dot` ys 

Cela signifie que xs et ys doivent être des listes de Num s. Cela conduit à une contradiction.


Une autre façon de regarder cela, est à un moment oublier la définition du type de dot. Cette ligne,

[email protected][xi,xs] `dot` [email protected][yi,ys] = xi*yi + (xs `dot` ys) 

indique que dot prend deux listes dont les éléments sont les arguments appropriés à dot. Mais la seule façon pour que cela ait du sens, c'est que ces listes soient imbriquées à l'infini. Ce n'est pas permis ni raisonnable.

+0

@Stephan: Merci pour l'explication. Je pense que cela clarifie pourquoi même la notation [xi: xs] a échoué, car le xs 'dot' ys impliquerait que xs et ys sont des listes de listes ... Faites-moi savoir si mon interprétation est valide. – Zaid

+0

@Zaid: c'est correct. Si 'xi :: a', alors' (xi: xs) :: [a] 'et' [xi: xs] :: [[a]] '. Donc faire correspondre sur [xi: xs] 'et ensuite passer récursivement' xs' conduira en effet à une erreur * type infini *. – Stephan202

Questions connexes