2010-10-29 8 views
5

Pourquoi le script Haskell suivant ne fonctionne-t-il pas comme prévu?Variables dans Haskell

find :: Eq a => a -> [(a,b)] -> [b] 
find k t = [v | (k,v) <- t] 

Compte tenu find 'b' [('a',1),('b',2),('c',3),('b',4)], l'interprète retourne [1,2,3,4] au lieu de [2,4]. L'introduction d'une nouvelle variable, appelée ci-dessous u, est nécessaire pour obtenir ce travail:

find :: Eq a => a -> [(a,b)] -> [b] 
find k t = [v | (u,v) <- t, k == u] 

Est-ce que quelqu'un sait pourquoi la première variante ne produit pas le résultat escompté?

+0

Répétez après moi: il n'y a pas de variables dans Haskell. ;-) Ce sont des symboles ou des identifiants. Les variables impliquent une variabilité. Chez Haskell, tout est immuable. –

+9

@Konrad Rudolph: Le rapport Haskell 98 utilise le terme «variable» partout. Il est important de noter que cela ne veut pas dire ce à quoi vous pouvez vous attendre, mais je ne pense pas qu'être plus persévérant que la documentation standard soit nécessairement utile. –

+4

@Konrad Rudolph: Sûrement vous plaisantez! Pourquoi, j'ai trouvé toute une section sur les variables [dans certains Haskell, ici] (http://books.google.com/books?id=27dkTJFrLZIC&pg=PA111). –

Répondre

14

De l'Haskell 98 Report:

Comme d'habitude, les liaisons dans la liste compréhensions peut dans les shadow portées externes; par exemple:

[ x | x <- x, x <- x ] = [ z | y <- x, z <- y]

Un autre point: si vous compilez avec -Wall (ou spécifiquement -fwarn-name-shadowing), vous obtenez l'avertissement suivant:

Warning: This binding for `k' shadows the existing binding 
      bound at Shadowing.hs:4:5 

L'utilisation -Wall est généralement une bonne idée - il mettra souvent en évidence ce qui se passe dans des situations potentiellement confuses comme celle-ci.

+0

+1 pour la suggestion de drapeau de citation et d'avertissement –

+0

Je pense que le problème ne concerne pas l'observation.Il s'agit en premier lieu de la signification d'un identificateur dans un modèle - il ne correspond pas à la valeur d'une variable avec cet identificateur, mais correspond à n'importe quoi et lie la valeur à une nouvelle variable avec cet identificateur – newacct

11

Le match de modèle (k,v) <- t dans le premier exemple crée deux nouvelles variables locales v et k qui sont avec le contenu du tuple t. La correspondance de modèle ne compare pas le contenu de t par rapport à la variable déjà existante k, elle crée une nouvelle variable k (qui masque la variable externe).

En règle générale, il n'y a jamais de "substitution de variable" se produisant dans un modèle, tous les noms de variables dans un modèle créent toujours de nouvelles variables locales.

3

Vous pouvez uniquement faire correspondre le motif sur les littéraux et les constructeurs.
Vous ne pouvez pas faire correspondre les variables. En savoir plus here.

Cela étant dit, vous pourriez être intéressé par les modèles de vue.