tipos opciones multiplos multiplicar imprimir hacer funciones definir como basico haskell typeclass standard-library

opciones - multiplos en haskell



Implementaciones alternativas de las clases de tipo de biblioteca estándar de Haskell (4)

He visto a muchas personas quejarse de algunas de las clases de tipos de la biblioteca estándar que dicen que "Mónada debería requerir Functor" o incluso "Mónada debería requerir Aplicativo", "El Solicitante debería requerir Señalado", "Núm. No debería requerir Mostrar" , etc, entonces, tengo algunas preguntas:

  1. ¿Existen argumentos sobre la forma en que el árbol de las dependencias de clase de tipo tiene esos "defectos" percibidos por la comunidad o es simplemente el resultado de cómo se hicieron las cosas históricamente?

  2. ¿Qué tan drásticamente un cambio en esto rompería el código existente?

  3. ¿Existen implementaciones alternativas de las clases de tipos básicos (especialmente flechas, mónadas, aplicativos, etc.) en torno a la implementación del conjunto "correcto" de dependencias de clase?


  1. Algunas personas o personas no identificadas (actuando a través de Vivian McPhail) han propuesto una reforma de esta área del preludio, y abren su propuesta al afirmar que "la jerarquía de clases estándar es una consecuencia del desarrollo histórico de Haskell, en lugar de la lógica". Si esto es cierto o no, no puedo decir.

  2. La propuesta anterior incluye medidas para respaldar la compatibilidad con versiones anteriores, pero parece que no sería perfecta de ninguna manera.

  3. Hubo un breve pero glorioso intento de crear El Otro Preludio para poner en orden un poco el desorden.


  1. Me opongo a la existencia vicaria y tampoco puedo tomar el crédito por la propuesta que está relacionada con las jerarquías Aplicativo-Functor-Monada. Yo había hecho murmullos hace años sobre la necesidad de un Preludio matemáticamente sound .

  2. Un obstáculo para una jerarquía de clases de tipos está presente desde el principio con los monoides. Por ejemplo, los enteros forman tanto un monoide aditivo como un multiplicativo. Coq resuelve esto a través de la herencia múltiple.

    Una gran ventaja de tener una jerarquía matemática con un sistema constructivo de pruebas de matemáticas es que podemos extraer programas de las pruebas a través del isomorfismo de Curry-Howard. Para aquellos interesados ​​en la corrección de programas y la verificación automática, contar con traducciones directas entre clases de tipos de Haskell y herramientas de verificación de pruebas como Coq es ingenioso.

    Actualmente utilizo el paquete hmatrix y amigos. Desafortunadamente, no creo que funcione bien con el Preludio numérico actual sobre hackage. Idealmente, para usar las bibliotecas BLAS y LAPACK optimizadas en código genérico, solo se debe implementar una interfaz de clase de tipo especificada en el Prelude numérico.


Ha habido una discusión reciente acerca de esto en la lista de Haskell-prime, creo que lo que se desprendió de allí es que para que ocurra un cambio de jerarquía, primero se debería implementar una propuesta de Jón Fairbairn, que corrige el muy, muy importante punto 1 de la lista de @ camccan: una clase de tipos podría dar implementaciones predeterminadas para sus definiciones de superclase. No conozco ninguna implementación, ni siquiera una especificación formal a medio camino de esa propuesta.

Tipo de clase de sinónimos punto de corrección # 2, hinchazón de contexto. Tenga en cuenta que ya puede hacer eso, siempre que esté de acuerdo con el uso de UndecidableInstances (y que GHC amplíe el sinónimo cada vez que infiere un tipo ...)

En cuanto al # 4, tener arreglos decentes para el # 1 y el # 2 corrige la mayoría de los problemas prácticos. Las cosas se vuelven más complicadas si no es una mera cuestión de granularidad (la respuesta es sinónimos, incluidas las instancias de escritura para los sinónimos de clase de tipo completo), pero teniendo la opción de múltiples superclases posibles, creo que esto surge cuando se trata de un número matemático. -la jerarquía . Una solución para eso (¿subclases alternativas?) Tiene una buena oportunidad de resolver el # 3 en el camino.

En cualquier caso, sin embargo, creo que el esfuerzo vale la pena, ya que los cambios realizados en Haskell (no solo en la jerarquía) definitivamente harían que tanto el código de Haskell como el de Haskell sean más flexibles y, por lo tanto, retiren la alfombra debajo del Argumentos actuales.


Más allá de la compatibilidad con versiones anteriores, hay algunos problemas (en su mayoría cosméticos, pero tediosos de tratar) debido a la forma bastante sencilla en que Haskell trata las clases de tipos:

No hay una definición implícita ascendente : la Monad está completamente definida simplemente por pure y (>>=) ; fmap y (<*>) se pueden escribir en términos de esos. En una jerarquía "adecuada", cada instancia debería escribirse. No es tan malo en este caso, pero a medida que aumenta la granularidad, también lo hace la cantidad de instancias en las que cada una agrega alguna función pequeña. Simplificaría sustancialmente las cosas si las definiciones de clase proporcionaran implementaciones predeterminadas para funciones de superclase en términos de sus propias funciones, de modo que las funciones como (>>=) que subsumen completamente múltiples funciones en superclases pueden servir como una definición para toda la jerarquía relevante.

Inflamación del contexto : en la medida en que hay una "razón" por la que Num requiere Show y Eq , es porque imprimir y comparar la igualdad de números es bastante común. Estos son estrictamente ortogonales, pero separarlos significa que las funciones que realizan las tres cosas ahora tienen que especificar las tres clases en su tipo. Esto es técnicamente algo bueno pero, nuevamente, a medida que aumenta la granularidad, también funcionarán las firmas de tipo.

Dependencias monolíticas : Se puede agregar una jerarquía de clases de tipos y sus superclases, pero no se pueden alterar ni reemplazar. Si un fragmento de código siente la necesidad de sustituir su propia versión de alguna clase de tipo común, por ejemplo, usar algo como esto para reemplazar la Monad jerarquía se corta en ese punto; la compatibilidad con el código que usa otras definiciones de Monad debe proporcionarse manualmente hasta cierto punto, y cualquier clase de tipo construida sobre la otra definición debe reimplementarse o traducirse incluso cuando se confía solo en un subconjunto de comportamiento que comparten ambas definiciones.

No hay una jerarquía claramente correcta : como lo implica lo anterior, hay opciones que se deben hacer en la granularidad de las clases. Por ejemplo, ¿es necesario que exista Pointed para existir, o solo es suficiente el Applicative ? Realmente no hay una respuesta aquí que sea universalmente ideal, y no debería haber ninguna.

Sospecho que los esfuerzos para reemplazar las clases de tipos existentes se atenderán mejor si primero se abordan los problemas anteriores, después de lo cual la sustitución de las clases de tipos será mucho menos dolorosa, o incluso poco más que una formalidad. La propuesta de sinónimos de clase de tipos que @luqui menciona, por ejemplo, sería un paso importante en esta dirección.