multiplos - multiplicar haskell
¿Qué usos has encontrado para los tipos de rango superior en Haskell? (4)
Eche un vistazo a las funciones como withRepoLock
en la fuente Darcs .
Darcs tiene soporte para múltiples formatos de repositorio, y ese soporte se expresa a través de una clase de tipos. Así que puedes escribir código que sea genérico sobre formatos de repositorio. Al leer realmente un repositorio en disco, desea enviar a ese código a través de un código común que determina en qué formato se encuentra el repositorio y elige la instanciación correcta de typeclass.
Los tipos de rango más alto parecen ser muy divertidos. Del wikibook de Haskell viene este ejemplo:
foo :: (forall a. a -> a) -> (Char,Bool)
foo f = (f ''c'', f True)
Ahora podemos evaluar foo id
sin explotar el compilador. Este ejemplo es seguido rápidamente en el libro por el ejemplo del mundo real que he visto en algunos otros lugares: la mónada ST y el runST
. Eso es muy bonito.
Pero todavía tengo que encontrar una situación en la que resuelvo un problema escribiendo mi propia función con un argumento de rango superior. ¿Tienes? ¿Qué ejemplos tiene de polimorfismo de rango 2 o de rango n en la naturaleza?
Es posible que haya encontrado problemas en los que los tipos de clasificación más alta serían útiles, pero no se dio cuenta. Por ejemplo, en el ejemplo de Darcs, podrían haberlo implementado fácilmente sin los tipos mejor clasificados. En su lugar, habría habido condiciones previas en algunas funciones que la persona que llama tendría que asegurarse de cumplir, como elegir la instanciación correcta de una función para el formato de repositorio.
La ventaja del tipo de clasificación más alta es que transfiere la responsabilidad de hacer esto correctamente desde el programador al compilador. Con el enfoque convencional, si un desarrollador de Darcs cometiera un error con el tipo de repositorio, el resultado sería un error en tiempo de ejecución o bien datos corruptos. Con el tipo de clasificación más alta, el desarrollador obtiene un error de tipo en el momento de la compilación.
Recientemente, alguien hizo una pregunta aquí en que podría resolverse con tipos de rango superior.
Otra aplicación está en el papel de desechar su placa de caldera .
Weirich y Washburnn "Boxes go Bananas"! ( paper , slides )
Aquí hay una explicación muy burda y probablemente un poco inexacta de lo que se trata: dado un tipo inductivo, BGB le permite representar el espacio de funciones de ese tipo que son "positivas": nunca discriminan entre sí sus argumentos. Como máximo, incluyen sus argumentos como parte de otros valores (generalmente del mismo tipo).
Weirich + Washburn usa esto para obtener una representación HOAS probablemente adequate del cálculo lambda en -XRankNTypes
Haskell (¿Alguien ha demostrado que sea adecuado todavía?).
Lo uso here (advertencia: código desordenado) para convertir un
(forall g . GArrow g => g () x -> g () y)
en una
(forall g . GArrow g => g x y)
Esto funciona porque el tipo polimórfico de rango 2 no puede "inspeccionar" la estructura de su argumento; todo lo que puede hacer es "pegar" ese argumento en estructuras más grandes. Algunos trucos me permiten averiguar dónde ocurre el pegado, y luego vuelvo a enhebrar el (los) punto (s) de pegado (si corresponde) a la entrada del GArrow
.
No puede hacer esto con la clase Control.Arrow
, porque todo el espacio de la función Haskell "se filtra" a través de arr
.