El compilador Glasgow Haskell ( GHC ) es un compilador de código nativo de código abierto para el lenguaje de programación funcional Haskell . [4] Proporciona un entorno multiplataforma para la escritura y prueba de código Haskell y admite numerosas extensiones, bibliotecas y optimizaciones que agilizan el proceso de generación y ejecución de código. GHC es el compilador Haskell más utilizado. [5] Los desarrolladores principales son Simon Peyton Jones y Simon Marlow .
Autor (es) original (es) | Kevin Hammond |
---|---|
Desarrollador (es) | El equipo de Glasgow Haskell [1] |
Versión inicial | Diciembre de 1992 [2] |
Lanzamiento estable | 9.0.1 / 4 de febrero de 2021 [3] |
Repositorio | |
Escrito en | Haskell y C |
Sistema operativo | Linux , OS X 10.7 Lion y posterior, iOS , Windows 2000 y posterior, FreeBSD , Solaris 10 y posterior |
Plataforma | x86 , x86-64 , BRAZO |
Disponible en | inglés |
Tipo | Compilador |
Licencia | Nueva licencia BSD |
Sitio web | www |
Historia
GHC comenzó originalmente en 1989 como un prototipo, escrito en LML (Lazy ML) por Kevin Hammond en la Universidad de Glasgow . Más tarde ese año, el prototipo fue reescrito por completo en Haskell, a excepción de su analizador , por Cordelia Hall, Will Partain y Simon Peyton Jones. Su primera versión beta fue el 1 de abril de 1991 y las versiones posteriores agregaron un analizador de rigor , así como extensiones de lenguaje como E / S monádicas , matrices mutables, tipos de datos sin caja, modelos de programación paralela y concurrente (como memoria transaccional de software y paralelismo de datos ). y un perfilador . [2]
Peyton Jones, así como Marlow, se trasladaron más tarde a Microsoft Research en Cambridge, Inglaterra , donde continuaron siendo los principales responsables del desarrollo de GHC. GHC también contiene código de más de trescientos contribuyentes. [1] Desde 2009, las contribuciones de terceros a GHC han sido financiadas por Industrial Haskell Group. [6]
Arquitectura
GHC en sí está escrito en Haskell , [7] pero el sistema de ejecución de Haskell, esencial para ejecutar programas, está escrito en C y C-- .
La interfaz de GHC, que incorpora el lexer , parser y typechecker, está diseñada para preservar tanta información sobre el idioma fuente como sea posible hasta que se complete la inferencia de tipos , con el objetivo de proporcionar mensajes de error claros a los usuarios. [2] Después de la verificación de tipos, el código Haskell se desazucara en un lenguaje intermedio escrito conocido como "Core" (basado en System F , extendido con expresiones let
y case
). Recientemente, Core se amplió para soportar tipos de datos algebraicas generalizadas en su sistema de tipo , y ahora se basa en una extensión a System F conocido como Sistema F C . [8]
En la tradición de la compilación dirigida por tipos, el simplificador de GHC, o "extremo intermedio", donde se realizan la mayoría de las optimizaciones implementadas en GHC, se estructura como una serie de transformaciones de fuente a fuente en el código Core. Los análisis y transformaciones realizados en esta etapa del compilador incluyen análisis de demanda (una generalización del análisis de rigurosidad ), aplicación de reglas de reescritura definidas por el usuario (incluido un conjunto de reglas incluidas en las bibliotecas estándar de GHC que realiza la fusión foldr / build ), despliegue (llamado " inlining "en compiladores más tradicionales), let-floating , un análisis que determina qué argumentos de función se pueden desempaquetar, análisis de resultado de producto construido , especialización de funciones sobrecargadas , así como un conjunto de transformaciones locales más simples como plegado constante y reducción beta . [9]
El back-end del compilador transforma el código Core en una representación interna de C--, a través de un lenguaje intermedio STG (abreviatura de "Spineless Tagless G-machine"). [10] El código C-- puede tomar una de tres rutas: se imprime como código C para su compilación con GCC , se convierte directamente en código de máquina nativo (la fase tradicional de " generación de código ") o se convierte a máquina virtual LLVM código para la compilación con LLVM. En los tres casos, el código nativo resultante finalmente se vincula con el sistema de tiempo de ejecución de GHC para producir un ejecutable.
Idioma
GHC cumple con los estándares de idiomas, tanto Haskell 98 [11] como Haskell 2010 . [12] También admite muchas extensiones opcionales del estándar Haskell: por ejemplo, la biblioteca de memoria transaccional de software (STM), que permite transacciones de memoria componible .
Extensiones a Haskell
Se han propuesto varias extensiones de Haskell. Estas extensiones proporcionan características que no se describen en la especificación del lenguaje o redefinen las construcciones existentes. Como tal, es posible que cada extensión no sea compatible con todas las implementaciones de Haskell. Hay un esfuerzo continuo [13] para describir extensiones y seleccionar aquellas que se incluirán en futuras versiones de la especificación del lenguaje.
Las extensiones [14] admitidas por el compilador Glasgow Haskell incluyen:
- Tipos y operaciones sin caja. Estos representan los tipos de datos primitivos del hardware subyacente, sin la dirección indirecta de un puntero al montón o la posibilidad de una evaluación diferida. El código numérico intensivo puede ser significativamente más rápido cuando se codifica con estos tipos.
- La capacidad de especificar una evaluación estricta para un valor, enlace de patrón o campo de tipo de datos.
- Sintaxis más conveniente para trabajar con módulos, patrones, listas por comprensión , operadores, registros y tuplas.
- Azúcar sintáctico para calcular con flechas y valores monádicos definidos de forma recursiva . Ambos conceptos amplían la notación do monádica proporcionada en Haskell estándar.
- Un sistema de tipos y clases de tipos significativamente más potente, que se describe a continuación.
- Template Haskell , un sistema para metaprogramación en tiempo de compilación . Un programador puede escribir expresiones que produzcan código Haskell en forma de árbol de sintaxis abstracta . Estas expresiones se verifican y evalúan en tiempo de compilación; el código generado se incluye luego como si hubiera sido escrito directamente por el programador. Junto con la capacidad de reflexionar sobre las definiciones, esto proporciona una poderosa herramienta para ampliar el lenguaje.
- Cuasi-cita, que permite al usuario definir una nueva sintaxis concreta para expresiones y patrones. La cuasi-cita es útil cuando un metaprograma escrito en Haskell manipula código escrito en un idioma que no sea Haskell.
- Clases de tipos genéricas , que especifican funciones únicamente en términos de la estructura algebraica de los tipos en los que operan.
- Evaluación paralela de expresiones utilizando múltiples núcleos de CPU. Esto no requiere que se generen subprocesos explícitamente. La distribución del trabajo ocurre implícitamente, en base a las anotaciones proporcionadas por el programador.
- Pragmas del compilador para dirigir optimizaciones como expansión en línea y funciones especializadas para tipos particulares.
- Reglas de reescritura personalizables. El programador puede proporcionar reglas que describen cómo reemplazar una expresión con una expresión equivalente pero evaluada de manera más eficiente. Estos se utilizan dentro de las bibliotecas de estructura de datos centrales para proporcionar un rendimiento mejorado en todo el código de nivel de aplicación. [15]
- Grabe la sintaxis de puntos. Proporciona azúcar sintáctico para acceder a los campos de un registro (potencialmente anidado) que es similar a la sintaxis de muchos otros lenguajes de programación. [dieciséis]
Extensiones del sistema de tipos
Un sistema de tipografía estática expresiva es una de las principales características definitorias de Haskell. En consecuencia, gran parte del trabajo en la extensión del lenguaje se ha dirigido hacia tipos y clases de tipos .
El Haskell Compiler Glasgow admite un sistema de tipo extendido basado en el teórico System F C . [8] Las principales extensiones del sistema de tipos incluyen:
- Polimorfismo de rango arbitrario e impredicativo . Esencialmente, una función polimórfica o un constructor de tipo de datos puede requerir que uno de sus argumentos sea polimórfico.
- Tipos de datos algebraicos generalizados . Cada constructor de un tipo de datos polimórfico puede codificar información en el tipo resultante. Una función que coincide con el patrón en este tipo puede usar la información del tipo por constructor para realizar operaciones más específicas en los datos.
- Tipos existenciales . Estos se pueden usar para "agrupar" algunos datos junto con operaciones sobre esos datos, de tal manera que las operaciones se pueden usar sin exponer el tipo específico de datos subyacentes. Este valor es muy similar a un objeto que se encuentra en los lenguajes de programación orientados a objetos.
- Tipos de datos que en realidad no contienen ningún valor. Estos pueden ser útiles para representar datos en metaprogramación a nivel de tipo .
- Familias de tipos : funciones definidas por el usuario de tipos a tipos. Mientras que el polimorfismo paramétrico proporciona la misma estructura para cada instanciación de tipos, las familias de tipos brindan polimorfismo ad hoc con implementaciones que pueden diferir entre las instanciaciones. Los casos de uso incluyen contenedores de optimización con reconocimiento de contenido y metaprogramación a nivel de tipo.
- Parámetros de función implícita que tienen alcance dinámico . Estos se representan en tipos de manera muy similar a las restricciones de clase de tipos.
- Tipos lineales (GHC 9.0)
Las extensiones relacionadas con las clases de tipos incluyen:
- Una clase de tipo se puede parametrizar en más de un tipo. Por lo tanto, una clase de tipos puede describir no solo un conjunto de tipos, sino una relación n -aria de tipos.
- Dependencias funcionales , que limitan partes de esa relación a ser una función matemática de tipos. Es decir, la restricción especifica que algún parámetro de clase de tipo está completamente determinado una vez que se fija otro conjunto de parámetros. Esto guía el proceso de inferencia de tipos en situaciones en las que, de lo contrario, habría ambigüedad.
- Reglas significativamente relajadas con respecto a la forma permitida de las instancias de clases de tipos. Cuando se habilitan en su totalidad, el sistema de clases de tipos se convierte en un lenguaje completo de Turing para la programación lógica en tiempo de compilación.
- Las familias de tipos, como se describió anteriormente, también pueden asociarse con una clase de tipos.
- La generación automática de determinadas instancias de clases de tipos se amplía de varias formas. Se admiten nuevas clases de tipos para programación genérica y patrones de recursividad comunes. Además, cuando un nuevo tipo se declara como isomorfo a un tipo existente, cualquier instancia de clase de tipo declarada para el tipo subyacente puede elevarse al nuevo tipo "gratis".
Portabilidad
Hay versiones de GHC disponibles para varias plataformas , incluidas Windows y la mayoría de las variedades de Unix (como Linux , FreeBSD , OpenBSD y macOS ). [17] GHC también se ha adaptado a varias arquitecturas de procesador diferentes . [17]
Ver también
- Abrazos
- Yhc
- Plataforma Haskell
Referencias
- ^ a b "El equipo de GHC" . Haskell.org . Consultado el 1 de septiembre de 2016 .
- ^ a b c Hudak, P .; Hughes, J .; Peyton Jones, S .; Wadler, P. (junio de 2007). "Una historia de Haskell: ser vago con la clase" (PDF) . Proc. Tercer Congreso ACM SIGPLAN de Historia de los Lenguajes de Programación (HOPL-III) . Consultado el 1 de septiembre de 2016 .
- ^ "Descargar - El compilador de Glasgow Haskell" . Haskell.org .
- ^ "Guía del usuario del sistema de compilación Glorious Glasgow Haskell" . Haskell.org . Consultado el 27 de julio de 2014 .
- ^ "Resultados de la encuesta sobre el estado de Haskell de 2017" . taylor.fausak.me . 15 de noviembre de 2017 . Consultado el 11 de diciembre de 2017 .
- ^ "Grupo Industrial Haskell" . Haskell.org . 2014 . Consultado el 1 de septiembre de 2016 .
- ^ "Comentario de GHC: el compilador" . Haskell.org . 23 de marzo de 2016. Archivado desde el original el 23 de marzo de 2016 . Consultado el 26 de mayo de 2016 .
- ^ a b Sulzmann, M .; Chakravarty, MMT; Peyton Jones, S .; Donnelly, K. (enero de 2007). "Sistema F con Coacciones de Igualdad de Tipo" . Proc. Taller de ACM sobre tipos en diseño e implementación de lenguajes (TLDI) .
- ^ Peyton Jones, S. (abril de 1996). "Compilación de Haskell por transformación de programa: un informe desde las trincheras" . Proc. Simposio Europeo de Programación (ESOP) .
- ^ Peyton Jones, S. (abril de 1992). "Implementación de lenguajes funcionales perezosos en hardware estándar: la máquina G sin etiquetas Spineless, versión 2.5" . Revista de programación funcional . 2 (2): 127–202. doi : 10.1017 / S0956796800000319 .
- ^ "Bibliotecas y lenguaje Haskell 98: el informe revisado" . Haskell.org . Consultado el 28 de enero de 2007 .
- ^ "Informe de idiomas Haskell 2010" . Haskell.org . Consultado el 30 de agosto de 2012 .
- ^ "Bienvenido a Haskell '(Haskell Prime)" . Haskell.org . Consultado el 26 de mayo de 2016 .
- ^ "Funciones de idioma de GHC" . Haskell.org . Consultado el 25 de mayo de 2016 .
- ^ Coutts, D .; Leshchinskiy, R .; Stewart, D. (abril de 2007). "Stream Fusion: de listas a streams y nada en absoluto" . Proc. Conferencia Internacional ACM SIGPLAN sobre Programación Funcional (ICFP) . Archivado desde el original el 23 de septiembre de 2007.
- ^ Mitchell, Neil; Fletcher, Shayne (3 de mayo de 2020). "Grabar sintaxis de puntos" . propuestas-ghc . GitHub . Consultado el 30 de junio de 2020 .
- ^ a b Plataformas en gitlab.haskell.org
enlaces externos
- La página de inicio de GHC