2009-01-10 19 views
6

estoy leyendo un tutorial que utiliza el siguiente ejemplo (que voy a generalizar un poco):Cuando se desestructuran las tuplas en Haskell, ¿dónde se pueden usar los elementos?

f :: Foo -> (Int, Foo) 
... 
fList :: Foo -> [Int] 
fList foo = x : fList bar 
    where 
    (x, bar) = f foo 

Mi pregunta radica en el hecho de que parece que se puede hacer referencia a x y bar, por su nombre, fuera del la tupla donde se obtienen. Esto parece actuar como una desestructuración de listas de parámetros en otros idiomas, si mi conjetura es correcta. (En otras palabras, no tuve que hacer lo siguiente :)

fList foo = (fst tuple) : fList (snd tuple) 
     where 
     tuple = f foo 

¿Tengo razón sobre este comportamiento? Nunca lo he visto mencionar en los tutoriales/libros que he estado leyendo. ¿Puede alguien indicarme más información sobre el tema?

Editar: ¿Se puede desestructurar algo (listas, matrices, etc.) de forma similar o solo se puede hacer con tuplas?

+1

Si finalmente no encuentra una explicación de la coincidencia de patrones en ese tutorial, es posible que desee complementarlo con una explicación más completa de Haskell. La coincidencia de patrones es básica e importante para el idioma. –

Respuesta

13

Al ver tu edición, creo que lo que su preguntando es Pattern matching.

Y para responder a su pregunta: Sí, cualquier cosa que pueda construir, también puede 'deconstruir' usando los constructores. Por ejemplo, probablemente esté familiarizado con esta forma de coincidencia de patrones:

head :: [a] -> a 
head (x:xs) = x 
head []  = error "Can't take head of empty list" 

Sin embargo, hay más lugares donde se puede utilizar la coincidencia de patrones, otras notaciones son válidos:

head xs = case xs of 
       (y:ys) -> y 
       []  -> error "Can't take head of empty list" 

head xs = let (y:ys) = xs 
      in y 

head xs = y 
    where 
    (y:ys) = xs 

Tenga en cuenta que la Los dos últimos ejemplos son un poco diferentes de los primeros porque dan diferentes mensajes de error cuando los llamas con una lista vacía.


Aunque estos ejemplos son específicos de las listas, se puede hacer lo mismo con otros tipos de datos, así:

first :: (a, b) -> a 
first tuple = x 
    where 
    (x, y) = tuple 

second :: (a, b) -> b 
second tuple = let (x, y) = tuple 
       in y 

fromJust :: Maybe a -> a 
fromJust ma = x 
    where 
    (Just x) = ma 

Una vez más, la última función también se bloqueará si se llama con Nothing.

En resumen; si puede crear algo usando constructores (como (:) y [] para listas, o (,) para tuplas, o Nothing y para Maybe), puede usar esos mismos constructores para hacer la coincidencia de patrones de varias maneras.

2

¿Tengo razón sobre este comportamiento?

Sí. Sin embargo, los nombres existen solo en el bloque donde los ha definido. En su caso, esto significa la unidad lógica a la que se aplica su cláusula where, es decir, la expresión dentro de fList.

0

Sí, tienes razón. Los nombres vinculados en una cláusula where son visibles a la declaración completa que precede a la cláusula where. En su caso, esos nombres son f y bar.

(Una de las cosas difíciles sobre el aprendizaje de Haskell es que no sólo se permite, sino común el uso de variables en el código fuente en lugares que preceden a los lugares donde se definen las variables.)

El lugar para leer más acerca de dónde se encuentran las cláusulas en el Haskell 98 Report o en uno de los muchos buenos tutoriales que se encuentran en haskell.org.

1

Otra forma de verlo es que un código como éste

x where x = 3 

es más o menos equivalente a

let x = 3 in x 
Cuestiones relacionadas