2010-12-12 15 views
12

lectura "mundo real Haskell" He encontrado algunas dudas intresting sobre tipos de datos:Haskell uso de tipos de datos buenos practicies

Esta coincidencia de patrones y posicional acceso a datos hacer que se vea como que tiene muy estrecho acoplamiento entre los datos y código que opera en él (intente agregar algo a Libro, o peor cambie el tipo de una parte existente).

Esto suele ser una cosa muy mala en imperativo (particularmente OO) idiomas ... ¿es que no se ve como un problema en Haskell? source at RWH comments

Y realmente, escribir algunos programas Haskell he encontrado que cuando hago pequeño cambio en la estructura de tipo de datos que afecta a casi todas las funciones que utilizan ese tipo de datos. Tal vez haya algunas buenas prácticas para el uso del tipo de datos. ¿Cómo puedo minimizar el acoplamiento de código?

Respuesta

13

Lo que está describiendo se conoce comúnmente como el problema de expresión - http://en.wikipedia.org/wiki/Expression_Problem.

Existe un compromiso definitivo, el código de haskell en general, y los tipos de datos algebraicos en particular, tienden a caer en el tipo difícil de cambiar pero son fáciles de agregar funciones sobre el tipo. Esto optimiza para (por adelantado) tipos de datos bien diseñados y completos.

Dicho todo esto, hay una cantidad de cosas que puede hacer para reducir el acoplamiento.

  • define bueno funciones de biblioteca, mediante la definición de un conjunto completo de combinadores y funciones de orden superior que son útiles para interactuar con sus tipo de datos que va a reducir el acoplamiento.A menudo se dice que, cuando se piensa en la coincidencia de patrones, existe una mejor solución que utiliza funciones de orden superior. Si buscas estas situaciones, estarás en un lugar mejor.

  • Exponga sus estructuras de datos como más tipos abstractos. Esto significa implementar todas las clases de tipos apropiadas. Esto ayudará a definir las funciones de la biblioteca, ya que obtendrá un montón de forma gratuita con cualquiera de las clases de tipos que implemente, por ejemplo, observe las operaciones sobre Functor o Monad.

  • Ocultar (tanto como sea posible) cualquier tipo de constructores. Los constructores exponen detalles de implementación y alentarán el acoplamiento. Sugerencia: esto se vincula con la definición de una buena API para interactuar con su tipo, los consumidores de su tipo rara vez, o nunca, tienen que usar los constructores de tipo.

La comunidad Haskell parece especialmente bueno en esto, si nos fijamos en muchas de las bibliotecas en hackage encontrará muy buenos ejemplos de implementación de clases de tipos y exponer buenas funciones de biblioteca.

+0

No creo que pueda llevarse bien sin la coincidencia de patrones. * Recursión explícita * sin embargo, raramente es necesaria. – delnan

+0

+1 por darle un nombre a la bestia. – fuz

7

En primer lugar, me gustaría mencionar que en mi opinión, hay dos tipos de acoplamientos:

  • Uno que hace que su alto el código para compilar cuando se cambia uno y olvidarse de cambiar al otro

  • uno que hace que su buggy código cuando cambia uno y se olvide de cambiar a la otra

si bien ambos son problemáticos, el primero es significativamente menos de ah dolor de cabeza, y ese parece ser el que está hablando.

Creo que el problema principal que mencionas se debe al uso excesivo de argumentos posicionales. Haskell casi te obliga a tener argumentos posicionales en tus funciones ordinarias, pero puedes evitarlos en tus productos tipo (registros).

Simplemente use registros en lugar de campos anónimos múltiples dentro de los constructores de datos, y luego puede emparejar con patrones cualquier campo que desee, por nombre.

bad (Blah _ y) = ...

good (Blah{y = y}) = ...

evitar el exceso de uso de tuplas, especialmente aquellos más allá de 2-tuplas, y liberalmente crear registros/Newtypes alrededor de cosas para evitar significado posicional.

+1

Gracias por su respuesta. No soy muy parecido a la sintaxis de registro porque el nombre de campo se vuelve global en el módulo. Tal vez hay alguna cura? – aindl

+0

IMO la cura está teniendo módulos muy pequeños :-) – Peaker

+0

@masterzim El problema de contaminación del espacio de nombres con los registros recibirá una revisión en una próxima versión de GHC, que le permitirá dar varios tipos con los mismos nombres de registro, y el accesorio funciona obtener de forma gratuita será general sobre los tipos que tiene ese campo de registro. – kqr

10

Además de lo que se ha dicho:

Un enfoque interesante es el estilo "scrap your boilerplate" de la definición de funciones sobre los tipos de datos, que hace uso de las funciones genéricas (en contraposición a la coincidencia de patrones explícita) para definir las funciones sobre el constructores de un tipo de datos. Si observa los documentos "deseche la plantilla", verá ejemplos de funciones que pueden hacer frente a los cambios en la estructura de un tipo de datos.

Un segundo método, como se señaló Hibberd, es utilizar pliega, mapas, se desarrolla, y otros combinadores de recursividad, para definir sus funciones. Cuando escribe funciones utilizando funciones de orden superior, con frecuencia se pueden tratar pequeños cambios en el tipo de datos subyacente en las declaraciones de instancia para Functor, Plegable, etc.

Cuestiones relacionadas