Pregunta

Proveniente de C++, me parece de programación genérica indispensable.Me pregunto cómo la gente se enfoque en Haskell?

Decir ¿cómo escribir genérica de la función de intercambio en Haskell?

Existe un concepto equivalente parcial de especialización en Haskell?

En C++, me parcialmente puede especializar la genérica de la función de intercambio con una especial para un genérico mapa/hash_map contenedor que tiene un especial método de intercambio de O(1) contenedor de intercambio.¿Cómo hacer que en Haskell o ¿cuál es el ejemplo canónico de la programación genérica en Haskell?

¿Fue útil?

Solución

Esto está estrechamente relacionado con su otra pregunta sobre Haskell y clasificación rápida. Creo que es probable que tenga que leer al menos el introducción de un libro sobre Haskell. Suena como si usted todavía no ha captado el punto clave sobre el que se es que le prohíbe a partir de la modificación de los valores de las variables existentes.

Intercambiar (tal como se entiende y se utiliza en C ++) es, por su propia naturaleza, todo sobre la modificación de los valores existentes. Es así que podemos usar un nombre para referirse a un contenedor, y reemplazar ese contenedor completamente diferentes contenidos, y especializado que la operación para ser rápido (y sin excepción) para los contenedores específicos, lo que nos permite implementar un enfoque de modificación-y-publicar (crucial para escribir código de excepción de seguridad o intentar escribir código sin bloqueo).

Puede escribir un intercambio genérico en Haskell, pero sería probable que tome un par de valores y devolver un nuevo par que contiene los mismos valores con sus posiciones invertidas, o algo por el estilo. No es realmente la misma cosa, y que no tiene los mismos usos. No tendría ningún sentido para tratar de especializarse para un mapa cavando dentro de ese mapa y el canje de sus variables miembro individuales, porque estás simplemente no les permite hacer cosas por el estilo en Haskell (se puede hacer la especialización, pero no la modificación de variables).

Supongamos que queremos "medida", una lista en Haskell:

measure :: [a] -> Integer

Esto es una declaración de tipo. Esto significa que el measure función toma una lista de cualquier cosa (a es un parámetro de tipo genérico, ya que comienza con una letra minúscula) y devuelve un entero. Así que esto funciona para una lista de cualquier tipo de elemento -. Que es lo que se llamaría una plantilla de función en C ++, o una función polimórfica en Haskell (no es lo mismo como clase polimórfica en C ++)

Ahora podemos definir que al proporcionar especializaciones para cada caso interesante:

measure [] = 0

es decir. medir la lista vacía y se obtiene cero.

Esta es una definición muy general que abarca todos los demás casos:

measure (h:r) = 1 + measure r

El bit entre paréntesis en la LHS es un patrón. Significa: tomar una lista, rompa la cabeza y lo llaman h, llame a la parte restante r. Esos nombres son entonces los parámetros que podemos utilizar. Esto coincidirá con cualquier lista con al menos un artículo sobre el mismo.

Si usted ha intentado metaprogramming plantillas de C ++ Todo esto va a ser viejo sombrero para usted, porque se trata de exactamente el mismo estilo - recursividad para hacer bucles, la especialización para hacer la recursión termina. Excepto que en Haskell es que funciona en tiempo de ejecución (especialización de la función de los valores o patrones de valores particulares).

Otros consejos

Como Earwicker EFS, el ejemplo no es tan significativa en Haskell. Si a pesar de todo quiere tener de todos modos, aquí es algo similar (el canje de las dos partes de una pareja), c & p de una sesión interactiva:

GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
Prelude> let swap (a,b) = (b,a)
Prelude> swap("hello", "world")
("world","hello")
Prelude> swap(1,2)
(2,1)
Prelude> swap("hello",2)
(2,"hello")

En Haskell, las funciones son genéricas (polimórficos) como sea posible - el compilador inferir que la "Mayoría de tipo general".Por ejemplo, TheMarko el ejemplo de swap es polimórfica por defecto en la ausencia de un tipo de firma:

*Main> vamos a swap (a,b) = (b,a)
*Main> :t swap
swap ::(t, t1) -> (t1, t)

Como por parciales de especialización, ghc tiene un no-98 extensión:
file:///C:/ghc/ghc-6.10.1/doc/users_guide/pragmas.html#especializamos-pragma

También, tenga en cuenta que hay un desajuste en la terminología.Lo que se llama genérica en c++, Java y C# se llama polimórficos en Haskell."Genéricos" en Haskell generalmente significa polytypic: http://haskell.readscheme.org/generic.html
Pero, más arriba yo uso el c++ significado de genéricos.

En Haskell, se crearía el tipo clases. clases de tipo no son como las clases de lenguajes orientados a objetos. Tomar la clase de tipo numérico Se dice que todo lo que es una instancia de la clase se puede realizar ciertas operaciones (+ - * /), de modo entero es un miembro del numérico y proporciona implementaciones de las funciones necesarias para ser consideradas numérico y se pueden utilizar en cualquier lugar de una se espera numérico.

Digamos que quiere ser capaz de foo Entrs y cuerdas. A continuación, se declararían Int y cadena que se va instancias de la clase Foo tipo. Ahora en cualquier lugar que aparezca el tipo (Foo a) ahora se puede utilizar Int o de cadena.

La razón por la cual no se puede agregar enteros y flota directamente es porque tiene el tipo de complemento (Numérico a) a -> a -> aa es una variable de tipo y al igual que las variables regulares que sólo se puede enlazar una vez tan pronto como a medida que se vincula a una Int cada una de la lista debe ser Int.

Después de leer lo suficiente en un libro de Haskell para comprender realmente la respuesta de Earwicker yo sugeriría leer también sobre el tipo clases. No estoy seguro de lo que significa “especialización parcial”, pero suena como que podría acercarse.

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