19 votos

Es "Lista" especialmente manejado en Haskell la coincidencia de patrón?

Soy un novato en Haskell y espero que esta pregunta no es tonta.

He visto tanta ejemplo de que cuando estoy teniendo una lista, yo soy capaz de igualar y se unen "composición el elemento de la lista para cada variable:

listSizeDesc :: [a] -> String
listSizeDesc [] = "Emtpy"
listSizeDesc (x:xs) = "Something inside"

Sin embargo, he tratado de hacer algo como:

foo :: Int -> String
foo 0 = "Zero"
foo (n - 1) = "next number is " ++ show n

No funciona.

A mí me parece que ambos (n-1) y (x:xs) describir cómo el argumento es "creado" y enlazar el "componente" para una discusión. Es la manera en la Lista de igualada especialmente diseñado para la facilidad de la recursividad? Coz que me parece esta coincidencia / argumento de unión de la lógica no se aplica a otras funciones, excepto (:).

18voto

Jeff Burka Puntos 2111

El problema que estamos encontrando es que la coincidencia de patrón sólo funciona con los datos de los constructores. Datos constructor es en esencia muy simple; sólo toma los valores de los datos y de los grupos juntos en algún tipo de estructura. Por ejemplo, data Foo = Bar a b simplemente toma dos piezas de datos y grupos de ellos juntos bajo el Foo etiqueta. El (:) función que se utiliza en su primer ejemplo es más que una función; es una de datos constructor. Se construye una nueva lista mediante la adición de la izquierda argumento el argumento de la derecha.

Ahora, el reconocimiento de patrones es simplemente hacer lo contrario de este proceso. Lo deconstruye un tipo de datos. Cuando usted escribe (x:xs) de su patrón, eres la extracción de las dos piezas de datos que el constructor originalmente cosidos juntos. Así que todos coincidencia de patrón que hace es extraer los datos que un constructor previamente cosidos juntos.

Hay una excepción: n+k patrones. En Haskell98, se permitió el uso de patrones de la forma (n+k). Esta fue una especie de arbitraria la excepción, y que recientemente fue eliminado. Si usted quisiera, usted todavía se puede utilizar si se incluyen los NPlusKPatterns idioma pragma.

14voto

Pierre Puntos 1854

El tipo de lista es de "Suma" escribir " con un constructor, algo como:

data List a =
     cons a (List a)
   | nil

Usted primer ejemplo es una coincidencia de patrón en un tipo de datos (con azúcar sintáctico para :).

El segundo ejemplo es un patrón de coincidencia en los números enteros, que no son un datatypye definición. Entero, no hay ningún patrón de uso de la sintaxis. Usted puede escribir su ejemplo con:

foo :: Int -> String
foo 0 = "Zero"
foo n = "next number is " ++ show (n+1)

En una nota de lado, si usted codificar números enteros con tipos de datos como:

data Nat = Zero | Succ Nat deriving (Show)

A continuación, puede utilizar su patrón de combinar como usted quería inicialmente.

foo :: Nat -> String
foo Zero = "Zero"
foo n@Succ(p) = "next number is " ++ show(n)

Aquí el patrón Succ(p) desempeña el papel de n-1.

5voto

Dan Burton Puntos 26639

Ya hay algunos grandes respuestas, así que no te molestes con la cuestión principal. Esto es no el mejor uso de él, pero lo que estaba tratando de hacer puede ser logrado con la vista de los patrones.

{-# LANGUAGE ViewPatterns #-}

foo :: Int -> String
foo 0 = "Zero"
foo (pred -> n) = "Next number is " ++ show n

4voto

amindfv Puntos 4668

Simplemente para ponerlo simple como sea posible:
Una lista de , literalmente, es una serie de concatenaciones. Un número que podría ser equivalente al resultado de una operación aritmética. La diferencia es que el resultado de a : b es, simplemente, a : b.


En más detalle:

Listas y (:) no son un caso especial. Vamos a hacer nuestra propia:

data List2 a = End               -- equivalent of "[]"
             | Cat a (List2 a)   -- non-infix ":"
  deriving (Show)

Por lo [1, 2, 3], que == (1 : (2 : (3 : []))), debería ser escrita como:

a = Cat 1 (Cat 2 (Cat 3 End))

Como coincidencia de patrón (x:xs), podemos patrón de coincidencia Lista2:

newTail End = End
newTail (Cat _ x) = x

Prueba esto:

*Main> tail [1,2,3]
[2,3]
*Main> newTail a
Cat 2 (Cat 3 End)

3voto

applicative Puntos 5690
moo :: Int -> String
moo 0 = "Zero"
moo n = "next number is " ++ show (n + 1)

n - 1 es una simple función de la aplicación, no un patrón. Una excepción se utiliza para + y este podría ser el modelo que usted está pasando. Usted puede escribir algo como

goo :: Int -> String
goo 0 = "Zero"
goo (n+1)  = "previous number is " ++ show n

en hugs ; usted todavía puede hacer esto con la ghc, si se incluye el pragma

{-#LANGUAGE NPlusKPatterns#-}

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X