Por favor, confirmar o corregir mi "inglés interpretación" de este fragmento de código Haskell

StackOverflow https://stackoverflow.com/questions/775730

Pregunta

Soy un C# desarrollador que está trabajando a través de "Mundo Real Haskell" para comprender realmente la programación funcional, de modo que cuando a aprender F#, que realmente va a grok y no sólo "escribir código C# a F#", por así decirlo.

Bueno, hoy me encontré con un ejemplo que yo pensaba que entendía 3 tiempos diferentes, sólo para ver luego algo me he perdido, la actualización de mi interpretación, y recurse (y maldición demasiado, creo yo).

Ahora creo que en realidad a lo que entiendo, y he escrito un detallado "inglés interpretación" a continuación.Puede usted Haskell gurús por favor, confirme que la comprensión, o señalar lo que me he perdido?

Nota:La Haskell fragmento de código (citado directamente desde el libro) es la definición de un tipo personalizado que está destinado a ser isomorfo a la construcción en Haskell tipo de lista.

El fragmento de código Haskell

data List a = Cons a (List a)
              | Nil
              defining Show

EDITAR:Después de algunas respuestas, veo que un malentendido que hizo, pero no estoy muy claro en la Haskell "análisis" de las reglas que corrija ese error.Por lo que he incluido mi original (incorrecto) interpretación a continuación, seguido de una corrección, seguido por la pregunta que aún queda claro para mí.

EDITAR:Aquí está mi original (incorrecto) "inglés interpretación" de la plantilla

  1. Yo soy la definición de un tipo llamado "Lista".
  2. El tipo de Lista es programable.Tiene un solo parámetro de tipo.
  3. Hay 2 valor de los constructores, que puede ser utilizado para hacer las instancias de la Lista.Un valor constructor es llamado "Nada" y el valor de las otras constructor es llamado "Contras".
  4. Si se utiliza el "Nil" constructor de valor, entonces no hay ningún campos.
  5. Los "Contras" constructor de valor tiene un único parámetro de tipo.
  6. Si se utiliza el "Contras" constructor de valor, hay 2 campos que deben ser proporcionados.El primer campo es una instancia de la Lista.El segundo campo obligatorio es una instancia de una.
  7. (He omitido intencionalmente nada acerca de la "definición de Espectáculo", porque no es parte de lo que me quiero centrar ahora mismo).

Corregido interpretación sería la siguiente (cambios en NEGRITA)

  1. Yo soy la definición de un tipo llamado "Lista".
  2. El tipo de Lista es programable.Es tiene un único parámetro de tipo.
  3. Hay 2 valor de constructores que puede ser utilizado para hacer instancias de Lista.Un constructor de valor es se llama "Nada" y el valor de las otras constructor es llamado "Contras".
  4. Si se utiliza el "Nil" constructor de valor, entonces no hay ningún campos.

    5.(esta línea ha sido eliminado ...no es exacto) de Los "Contras" constructor de valor tiene un único parámetro de tipo.

  5. Si se utiliza el "Contras" constructor de valor, hay 2 campos la cual debe ser proporcionada.La primera campo obligatorio es una instancia de una.El segundo es un campo requerido ejemplo de "Lista-de-un".

  6. (He omitido intencionalmente nada acerca de la "definición de Espectáculo", porque no es parte de lo que me quiero centrar ahora mismo).

La pregunta que todavía no está claro

La confusión inicial fue con respecto a la parte del fragmento que dice "Contras de un (Lista)".De hecho, esa es la parte que todavía no está claro para mí.

Algunas personas han señalado que cada elemento en la línea después de los "Contras" token es un tipo de, no un valor.Lo que significa que esta línea dice "Los Contras valor constructor tiene 2 campos:uno de tipo 'a' y la otra de tipo 'lista-de-un"."

Que es muy útil saber.Sin embargo, algo que todavía no está claro.Al crear instancias con las Contras constructor de valor, esos casos de "interpretar" la primera 'a' con el significado de "lugar del valor que se pasa aquí." Pero lo hacen no interpretar la segunda 'a' de la misma manera.

Por ejemplo, considere la posibilidad de este INTÉRPRETE de la sesión:

*Main> Cons 0 Nil
Cons 0 Nil
*Main> Cons 1 it
Cons 1 (Cons 0 Nil)
*Main> 

Cuando yo escriba "Contras 0 Nil", utiliza los "Contras" valor constructor para crear una instancia de la Lista.De 0, se entera de que el parámetro de tipo "Integer".Hasta el momento, no hay confusión.

Sin embargo, también determina que el valor el primer campo de las Desventajas es 0.Sin embargo, se determina nada acerca de la valor de la segunda campo ...sólo se determina que el segundo campo tiene un tipo de de la Lista de "Integer".

Así que mi pregunta es, ¿por qué "a" en el primer campo significa "el tipo de este campo es la 'a' y el valor de este campo es" a", mientras que "a" en el segundo campo de los medios sólo "el tipo de este campo es el de la "Lista de un'"?

EDITAR:Creo que ahora he visto la luz, gracias a varias de las respuestas.Permítanme expresarlo aquí.(Y si de alguna manera es todavía incorrecta de alguna manera, por favor, por todos los medios que me haga saber!)

En el fragmento de "los Contras de un (Lista)", estamos diciendo que los "Contras" constructor de valor tiene dos campos, y que el primer campo es de tipo 'a', y que el segundo campo es de tipo 'Lista'.

Eso es todo lo que estamos diciendo! En particular, estamos diciendo NADA acerca de los valores!Este es un punto clave que me faltaba.

Más tarde, queremos crear una instancia, utilizando los "Contras" constructor de valor.El tipo que esta en el intérprete:"Contras 0 Nil".Este explícitamente le dice a los Contras constructor de valor de uso de 0 para el valor del primer campo, y el uso de Nil como el valor del segundo campo.

Y eso es todo allí está a él.Una vez que usted sabe que el valor constructor definición especifica nada, pero los tipos de, todo se vuelve claro.

Gracias a todos por los amables respuestas.Y como dije, si algo está todavía fuera, por favor, por todos los medios que me lo cuentes.Gracias.

¿Fue útil?

Solución

  • Los "Contras" constructor de valor tiene un único parámetro de tipo.

Nope:ya ha parametrizado es cuando se declara data List a.Un efectivo de la propiedad de este es que si tengo un Nil ::Lista de Int, no puedo intercambio con un Nil ::Lista De Char.

  • Si se utiliza el "Contras" constructor de valor, hay 2 campos que deben ser proporcionados.El primer campo es una instancia de la Lista.El segundo campo obligatorio es una instancia de una.

Tienes que intercambia:el primer campo es una instancia de una, el segundo campo es un ejemplo de la Lista.

Este capítulo de Mundo Real Haskell puede ser de su interés.

Gracias.Que es el capítulo en que estoy ahora.Así que ...cuando el código dice que "los Contras de un (Lista)", pensé que los "Contras" parte de que estaba declarando que los Contras constructor de valor se parametrizó.Es que aún no han cubierto la sintaxis para parametrizar los tipos, por lo que supuse que la sintaxis debe requerir re-afirmando que "en un" si usted va a utilizar una.Pero usted está diciendo que no es necesario?Y por lo tanto eso no es lo que "a" significa?

Nope.Una vez que declarar un parámetro en nuestro tipo, llegamos a la reutilización de otra manera para decir "que debería ser ahí". Es un poco como un a -> b -> a tipo de firma:una es la parametrización del tipo, pero entonces tengo que usar el mismo como el valor de retorno.

OK, pero esto es confuso.Parece que la primera "a" significa "el primer campo es una instancia de una",

Nope, que es no verdadero.Simplemente significa que el tipo de datos parametrizes sobre algún tipo de una.

y TAMBIÉN significa "el primer campo tiene el mismo valor que el valor que se pasa en una".En otras palabras, especifica el tipo Y valor.

No, eso tampoco es verdad.

He aquí un ejemplo muy instructivo, la sintaxis de las que puede o no haber visto antes:

foo :: Num a => a -> a

Esto es bastante estándar de firma para una función que toma un número y le hace algo a ella y le da otro número.Lo que en realidad significa "un número" en Haskell-hablar, sin embargo, es arbitraria en el tipo "a" que implementa el "Num" de la clase.

Por lo tanto, esta analiza el inglés:

Vamos a indicar un tipo de aplicación de la Num typeclass, luego de la firma de este método es un parámetro con el tipo a, y el valor de retorno del tipo de una

Algo similar ocurre con los datos.

También se me ocurre que la instancia de la Lista en la especificación de los Contras también es confuso usted:ser muy cuidadoso al analizar que:mientras que los Contras es que especifica un constructor, que es básicamente un patrón que Haskell es ir a la envoltura de los datos, (Lista) se parece a un constructor, pero en realidad es simplemente un tipo, como Int o Double.una es un tipo, NO es un valor en cualquier sentido del término.

Editar: En respuesta a la más reciente edición.

Creo que una disección primero se llama para.A continuación, voy a tratar con sus preguntas punto por punto.

Datos de Haskell constructores son un poco raro, porque definir el constructor de la firma, y usted no tiene que hacer cualquier otro andamio.Tipos de datos en Haskell no tienen ninguna noción de variable miembro.(Nota:hay una sintaxis alternativa que esta forma de pensar es más susceptible, pero vamos a ignorar que, por ahora).

Otra cosa es que Haskell código es densa;su tipo de firma son como eso.Así que esperar a ver el mismo símbolo reutilizados en diferentes contextos.Tipo de inferencia también juega un papel importante aquí.

Así que, de vuelta a su tipo:

data List a = Cons a (List a)
              | Nil

Yo fragmento de esta en varios pedazos:

data Una lista de

De esta forma se define el nombre del tipo, y cualquier tipos parametrizados que tendrá más adelante.Tenga en cuenta que sólo ver este espectáculo en otro tipo de firmas.

Contras a (List a) |
Nil

Este es el nombre de los datos del constructor. Este NO ES un tipo de.Podemos, sin embargo, el patrón se ajusta a él, ala:

foo :: List a -> Bool
foo Nil = True

Observe cómo la Lista a es el tipo en la firma, y Nil es tanto de los datos del constructor y la "cosa" que nos coincidencia de patrón para.

Cons un (Lista)

Estos son los tipos de los valores que la ranura en el constructor.Contras tiene dos entradas, una es de tipo a, y uno es de tipo Lista una.

Así que mi pregunta es, ¿por qué "a" en el primer campo significa "el tipo de este campo es la 'a' y el valor de este campo es" a", mientras que "a" en el segundo campo sólo quiere decir "el tipo de este campo es el de la "Lista de un'"?

Simple:no creo que esto es como nosotros especificando el tipo;piense en ello ha Haskell es la inferencia del tipo fuera de él.Así que, para nuestros efectos, simplemente estamos pegando un 0, y un Nulo en la segunda sección.Entonces, Haskell se ve en nuestro código y piensa:

  • Hmm, me pregunto qué tipo de Contras 0 Nil
  • Así, los Contras es un constructor de Lista de una.Me pregunto qué tipo de Lista es un
  • Bueno, una se utiliza en el primer parámetro, de modo que desde el primer parámetro es un entero (Int otra simplificación;0 es en realidad una cosa extraña que es typeclassed como Num), lo que significa una es un Num
  • Hey, bueno, eso también significa que el tipo de Nil es la Lista de Int, aunque no hay nada allí que en realidad iba a decir que

(Nota, que no es en realidad cómo se implementa.Haskell puede hacer un montón de cosas extrañas mientras que la inferencia de tipos, que es en parte por qué los mensajes de error chupar.)

Otros consejos

Las analogías son por lo general carecen de todo tipo de formas, pero ya que usted sabe C# pensé que esto podría ser útil.

Esta es la descripción de la List a definición en C#, tal vez esto aclare algunas cosas (o, más probablemente, confunde aún más).

class List<A>
{
}

class Nil<A> : List<A>
{
    public Nil() {}
}

class Cons<A> : List<A>
{
    public A Head;
    public List<A> Tail;

    public Cons(A head, List<A> tail)
    {
        this.Head = head;
        this.Tail = tail;
    }
}

Como se puede ver;

  • el List el tipo tiene un único parámetro de tipo (<A>),
  • el Nil constructor no tiene parámetros,
  • y el Cons constructor de dos parámetros, un valor head de tipo A y un valor tail de tipo List<A>.

Ahora, en Haskell la Nil y Cons son sólo los constructores de la List a tipo de datos en C# son también los tipos en y de sí mismos, de modo que es donde la analogía falla.

Pero espero que esto le da algo de sentido intuitivo de lo que los diferentes A's representan.

(Y por favor comentar como esta horrible comparación no hace justicia a Haskell tipos de datos.)

Cons a (List a)

El primer campo de un contra es un valor de tipo "a".El segundo es un valor de tipo "List a", es decir,una Lista de parámetros con el mismo tipo como el parámetro de la lista actual.

5 está mal, y yo diría que de las 6 de la siguiente manera para sustituir:

Contras{1} a{2} (Lista a){3} es un constructor llamado Contras (la parte antes de {1}) para un valor de la Lista de tipo a (los datos de la Lista de una parte) que necesita dos valores:uno de tipo a (la parte entre {1} y {2}) y uno de la Lista de tipo a(la parte entre {2} y {3}).

Para ayudar a usted con una aparente fuente de confusión:en Haskell que casi nunca tienen que dar explícita de los parámetros de tipo de tipo de inferencia para deducir el tipo de sus valores.Entonces, en un sentido, sí, cuando se pasa un valor a una función o constructor, también puede especificar un tipo, a saber.el tipo de en el valor pasado.

Sí, la sintaxis de los datos es un poco confuso, ya que los juegos de palabras y nombres de tipos y en realidad no hacen una sintáctica distinción entre ellos.En particular, en un constructor de la definición de:

Cons a (List a)

La primera palabra es el nombre del constructor;cada palabra es el nombre de algunos predeclared tipo.Por lo tanto a y List a ya están en el alcance (la a fue llevado en el alcance de la a en "data List a"), y usted está diciendo que esos son los tipos de los parámetros.Su papel podría ser mejor demostrado afirmando lo mismo con registro de sintaxis:

Cons { headL :: a, tailL :: List a }

I. e.un valor de tipo List Int, si fue construido con la Cons constructor, tiene dos campos:un Int y un List Int.Si se ha construido con Nil, no tiene campos.

Cuando escribo "Cons 0 Nil", se utiliza el "Cons"valor constructor para crear una instancia de la Lista.De 0, se entera de que el parámetro de tipo "Integer".Hasta el momento, no hay confusión.

Sin embargo, también se determina que el valor del primer campo de las Desventajas es 0.Aún no se determina nada sobre el valor del segundo campo ...sólo se determina que el segundo campo tiene un tipo de "Lista de Enteros".

No, se determina que el segundo valor del campo es Nil.Dada su definición, Nil es un valor del tipo List a.Por lo tanto, también lo es Cons 0 Nil.Y en Cons 1 it el segundo valor del campo es it;es decir, Cons 0 Nil.Esto es precisamente lo que el REPL muestra:Cons 1 (Cons 0 Nil).

Miré a tu editado pregunta.

Al crear instancias con las Contras constructor de valor, esos casos "interpretar" la primera 'a' en el sentido de "coloque el valor pasado aquí.

En "los Contras de un (Lista a)", "a" y de la "Lista a" son tipos.No entiendo lo de "valor" tiene para con él.

Cuando yo escriba "Contras 0 Nulo", se utiliza el Los "contras" valor constructor para crear una ejemplo de Lista.De 0, aprende que el parámetro de tipo "Integer".Hasta el momento, no hay confusión.

Sin embargo, también se determina que la valor del primer campo de las Contras es 0.Aún no se determina nada acerca de el valor del segundo campo ...es sólo determina que el segundo campo tiene un tipo de "Lista de Enteros".

El valor del segundo campo es Nil.

Así que mi pregunta es, ¿por qué "a" en el primer campo significa "el tipo de este campo es 'a' y el valor de este campo es 'a'", mientras que "a" en la segunda campo significa sólo "el tipo de este es el de "Lista de un'"?

""en el primer campo significa "el tipo de este campo es la 'a'".La "lista a" en el segundo campo significa "el tipo de este campo es el de la "Lista a".En el caso de los "Contras 0 Nil" por encima de, 'a' se infiere que el "Entero".Así que los "Contras de un (Lista a)" se convierte en "Contras Entero (Lista Entero)".El 0 es un valor de tipo Integer.El Nil es un valor de la Lista "tipo Entero".

el valor de este campo es la 'a'

No entiendo lo que quieres decir con esto.'a' es una variable de tipo;qué tiene que ver con los valores?

Sólo para darle algo más de "ayuda", en caso de que usted todavía está viendo este hilo.Haskell tiene un par de convenios que desordena las ideas de los demás de cómo las cosas deberían hacerse en Haskell, un tipo en parámetros es tan comúnmente aceptado, que es generalmente considerado como un tipo de nivel de la función.Asimismo, el valor de los constructores son considerados como "especiales" de las funciones, que también permite la coincidencia de patrones, además de su "toma un valor (o más) y producen un valor como resultado".

Otro "gracioso" característicos de Haskell es que no se menciona explícitamente (o implícitamente) evaluar los argumentos a una función, incluso si el argumento está en paréntesis.Permítanme decir que de forma ligeramente diferente:Haskell funciones no evaluar los argumentos entre paréntesis antes que el resto de los argumentos.Los argumentos que se ponen entre paréntesis para agrupar sólo a los efectos de, no se han evaluado de "primera".Haskell asigna a los argumentos ("se aplica") de una función en una prioridad más alta que la de cualquier otra operación - incluso superior a la de una función implícita de la aplicación de uno de sus propios argumentos.Esta es la razón por la Cons constructor ha paréntesis alrededor del segundo argumento, (List a) - para decirle al compilador que Cons tiene dos argumentos, y no tres.Los paréntesis son para la agrupación, y no sólo para la prioridad!

Como un poco de un lado el tema, tenga cuidado con los tipos en F#.Puesto que F# tiene sus raíces en ML, sus tipos parametrizados tener los parámetros en la frente - int list, no (List Int) en la parte de atrás!Haskell hace la otra manera, porque de la misma manera que Haskell hace las funciones - en primer lugar la función, los argumentos a la función.Esto fomenta un uso común en el patrón, y explica por qué Haskell tipos y el valor de constructores con Mayúsculas - para recordarle que usted está tratando con un tipo/clase relacionados con la cosa.

Bueno, estoy hecho;gracias por dejarme poner este enorme Pared O' Texto en su propiedad...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top