Glasgow Haskell Compiler
The Glasgow Haskell Compiler (GHC) is an open-source, native-code compiler and interactive environment for the functional programming language Haskell, serving as its primary implementation and supporting compilation to machine code, LLVM bitcode, or C.[1] It includes the GHCi REPL for interactive development and features extensive optimizations, lazy evaluation, type inference, and support for Haskell language extensions such as type classes and monads.[2] Developed collaboratively by a global community under guidance from the University of Glasgow and contributors including Simon Peyton Jones, GHC has evolved into a robust tool used in academia, research, and industry for building reliable, high-performance software.[3] GHC originated in 1989 at the University of Glasgow as an academic project funded by the UK government, emerging from efforts to implement the newly designed Haskell language.[3] A prototype was created in January 1989 by Kevin Hammond using the Lazy ML (LML) system, becoming operational by June, with full development starting in autumn under Cordelia Hall, Will Partain, and Simon Peyton Jones, who implemented it in Haskell itself.[3] The first public beta release arrived on April 1, 1991, followed by version 0.10 in December 1992, aligning with the Haskell 1.0 standard.[3] Early milestones included the addition of monadic I/O in July 1993 and multi-parameter type classes in version 3.00 (1997), solidifying GHC's role in advancing Haskell's type system and practicality.[3] Architecturally, GHC consists of a frontend for parsing, renaming, and type checking Haskell source; an intermediate representation called Core (a variant of System FC, a typed lambda calculus); multiple optimization phases; and backends for code generation, complemented by a runtime system (RTS) written in C that manages garbage collection, lightweight threads, and concurrency.[2] Key technical contributions include the Spineless Tagless G-machine for efficient lazy evaluation (1992) and short-cut deforestation optimizations using the foldr/build rule (1993), enabling high-performance execution on standard hardware.[3] Today, GHC supports Haskell 2010 and later revisions, with ongoing enhancements like parallel programming via GHC extensions and integration with tools such as QuickCheck for property-based testing; the latest stable release as of September 2025 is version 9.10.3.[1][3]Overview
Description
The Glasgow Haskell Compiler (GHC) is an open-source native code compiler for the Haskell programming language, originally developed at the University of Glasgow starting in January 1989.[4] Haskell is a standardized, general-purpose, purely functional programming language characterized by lazy evaluation, where expressions are evaluated only when needed, enabling referential transparency and immutability as core principles.[5] GHC serves as the de facto standard implementation of Haskell, supporting the Haskell 2010 language standard while providing extensive extensions for advanced features.[6] GHC's primary functionalities include compiling Haskell source code into standalone executable binaries for various platforms, often leveraging optimizations for high performance. It also offers an interactive mode via GHCi, allowing developers to evaluate expressions, load modules, and debug code in real time. Additionally, GHC generates intermediate representations such as Core, a simplified functional language, which facilitates analysis, optimization, and integration with other tools in the Haskell ecosystem. The compiler's first public beta release occurred on April 1, 1991, marking an early milestone in its evolution from an academic project to a robust tool.[4] Today, GHC plays a pivotal role in academia for advancing functional programming research, including type systems and optimization techniques, and in industry for building reliable, concurrent systems in domains like finance and aerospace.[2][7]Licensing and Availability
The Glasgow Haskell Compiler (GHC) is released under the BSD 3-clause license, a permissive open-source license that allows users to freely use, modify, and distribute the software, provided they retain the original copyright notice, conditions, and disclaimer in all copies or substantial portions of the software.[8] This licensing framework has been in effect since 2007, succeeding earlier custom license terms that were revised to facilitate wider adoption and integration within the open-source ecosystem.[9] GHC is publicly available through official downloads on the Haskell website, offering pre-built binary packages tailored for major operating systems and architectures such as Linux (x86_64 and AArch64), macOS (x86_64 and ARM64), Windows (x86_64), and others including FreeBSD.[1] The complete source code resides in a GitLab repository, which has hosted the project since its migration from earlier version control systems in December 2018, enabling developers to clone, fork, and submit contributions via merge requests.[10] Users can install GHC via straightforward binary installers provided in the downloads, which include platform-specific setup scripts and integrate GHC with tools like the interactive environment GHCi.[1] Alternatively, package managers simplify the process: on macOS, Homebrew users can runbrew install ghc to fetch and configure the latest stable version; on Windows, Chocolatey supports installation with choco install ghc, handling dependencies automatically.[11][12] For advanced users preferring customization, building GHC from source is supported on POSIX-compliant systems, requiring a bootstrapping GHC installation (version 9.0.1 or later) and external dependencies such as the lexical analyzer tool Alex (version 3.2.6 or later), the parser generator Happy (version 1.19.9 or later), GCC or Clang, GNU Make, Python, and autotools like Autoconf and Automake; comprehensive build instructions outline platform-specific prerequisites and compilation steps.[13][14]
Distributing GHC derivatives, modified versions, or contributions must comply with the BSD 3-clause terms, which prohibit the use of the University of Glasgow's or contributors' names for endorsement or promotion without prior written permission, while ensuring the license notice accompanies all redistributions to maintain transparency and legal clarity.[8]
History
Origins and Early Development
The Glasgow Haskell Compiler (GHC) was founded in January 1989 at the University of Glasgow as part of the broader effort to implement the newly designed Haskell programming language, which sought to standardize non-strict, purely functional programming following the Haskell 1.0 report published in April 1990.[4] This initiative emerged from the need for an efficient, portable compiler to demonstrate the viability of lazy evaluation in Haskell, a feature that delayed computation until values were required, enabling more expressive and modular code compared to earlier strict languages.[4] Prior implementations like Lazy ML (LML) from Chalmers University, a lazy functional language with efficient graph reduction via the G-machine, and Yale Haskell, a lazy but less community-oriented effort led by Paul Hudak, highlighted the demand for a robust, optimizing Haskell compiler to support research and practical applications.[4][15] Early development involved a core team of researchers focused on creating a prototype to validate Haskell's design, with Kevin Hammond leading the initial implementation in LML as a front-end to the Chalmers LML compiler, achieving functionality by June 1989 and incorporating Haskell 1.0 features like type classes.[4] Simon Peyton Jones joined the project in autumn 1989, alongside Cordelia Hall and Will Partain, bringing expertise in functional language implementation; Peyton Jones would go on to lead GHC's development until 2019.[4] Additional key contributors included Lennart Augustsson from Chalmers, who contributed to Haskell's committee and later developed the HBC compiler, as well as collaborators from Yale such as Paul Hudak and from Edinburgh like Philip Wadler, reflecting the multi-institutional ties that drove Haskell's creation.[4] The first GHC prototype, bootstrapped in Haskell itself, utilized combinator-based graph reduction techniques to handle lazy evaluation efficiently, with the initial working version ready by early 1990. This culminated in the first beta release on April 1, 1991, which supported core Haskell semantics and marked a milestone in proving lazy functional programming's practicality.[4] Early work was funded primarily through UK public grants, including SERC support for the GRASP project (grants GR/F98444 and GR/F34671) and joint DTI/SERC funding for related functional language research, enabling the academic collaboration at Glasgow.Major Releases and Milestones
The Glasgow Haskell Compiler (GHC) achieved full compliance with the Haskell 98 standard in version 6.0, released on May 28, 2003, marking a significant milestone in stabilizing the language implementation for broader adoption.[16][17] This release focused on refining the core compiler to align precisely with the revised Haskell 98 specification from December 2002, enabling reliable use in production environments. Subsequent versions built on this foundation, with GHC 7.0.1, released on November 16, 2010, introducing support for the Haskell 2010 standard by default, which incorporated extensions like foreign function interface improvements and conditional compilation.[18][19] Later releases emphasized advanced language features, such as GHC 9.0.1 in February 2021, which debuted the LinearTypes extension for resource-sensitive programming, allowing linear types to enforce single-use semantics for values like file handles or continuations.[20][21] GHC 9.4, released in August 2022, added the OverloadedRecordDot extension, enabling more ergonomic record field access via dot notation that supports overloading for custom types.[22][23] As of November 2025, the most recent stable LTS release is GHC 9.10.3, released on September 10, 2025.[24] Key milestones include the introduction of the interactive GHCi environment in GHC 5.00 (April 2001), which revolutionized development by providing an REPL for rapid prototyping and debugging.[25] The LLVM backend arrived around 2009–2010, offering an alternative code generation path that improved performance on certain architectures through LLVM's optimization infrastructure.[26][27] From 2009 to 2014, the Industrial Haskell Group (IHG) provided targeted funding for GHC enhancements, such as dynamic library support on Linux and Windows, addressing industrial needs for deployable binaries.[28][29] In 2018, GHC migrated its source repository to Git and GitLab, streamlining collaboration and issue tracking for the open-source community.[30] GHC adopted a semantic versioning scheme starting with major version 8.0 in 2017, where major releases introduce potentially breaking changes, minor versions add features compatibly, and patch releases focus on fixes, exemplified by the structured progression from 8.0 to subsequent series.[22] This aligns with a consistent release cadence of approximately six months for major versions since the mid-2010s, ensuring timely delivery of innovations while maintaining stability for long-term support (LTS) branches like 9.6 and 9.10. In July 2025, GHC announced a new LTS release policy, with the first LTS branch planned for 9.14 in August 2025.[31][32] In 2024, GHC deprecated support for 32-bit platforms on Darwin (macOS/iOS) and Windows, reflecting declining hardware relevance and developer resource constraints, with binary distributions ceasing and future removal planned.[33] Community governance has evolved with significant involvement from Well-Typed, a consultancy firm that has contributed extensively to GHC development since 2008, including core optimizations and release engineering.[34] The Haskell Prime process, which guides revisions to the Haskell standard, draws heavily from GHC extensions, ensuring that innovations like linear types influence future specifications through committee review. This collaborative model, bolstered by IHG's earlier efforts and ongoing foundation support, underscores GHC's role as the de facto reference implementation.Architecture
Frontend
The frontend of the Glasgow Haskell Compiler (GHC) comprises the initial compilation stages that transform Haskell source code into an intermediate representation suitable for further processing. It handles lexical analysis, parsing, name resolution, type inference and checking, and desugaring, ensuring adherence to Haskell's syntax and semantics while providing robust diagnostics for errors encountered during these phases. This pipeline operates on modules independently where possible, supporting features like Template Haskell splicing that may require iterative passes.[2] Lexical analysis begins with a lexer generated by the Alex tool, which scans the input source file character by character to produce a stream of tokens according to Haskell's lexical conventions, including identifiers, literals, keywords, and symbols. The lexer supports Haskell's layout rule, which uses indentation to imply syntactic structure such as block delimiters, by tracking position information in tokens to enable context-sensitive parsing. This stage filters out comments and whitespace, ensuring the token stream accurately reflects the program's structure without extraneous elements.[2] The parser, implemented using the Happy parser generator from the grammar defined incompiler/GHC/Parser.y, consumes the token stream to construct an abstract syntax tree (AST) in the HsSyn representation, where identifiers are initially raw strings (RdrName). It handles Haskell's context-free grammar, including layout-sensitive constructs like where clauses and list comprehensions, and produces a parse tree that preserves source positions for error reporting. The parser is designed to be modular, allowing reuse in tools like GHCi for interactive input.[2]
The renamer follows parsing and resolves all occurrences of identifiers to unique, qualified names (Name) in the HsSyn AST, managing Haskell's module system by processing import and export declarations to build a global name environment. It handles scoping rules, including lexical scoping, qualified imports, and re-exports, while detecting ambiguities such as name clashes or shadowed bindings and flagging unused imports or local definitions as warnings. Additional tasks include fixing the precedence of infix operators based on their declared fixity and expanding parentheses in expressions to explicit applications. The renamer operates in a single pass per module, producing a renamed AST (HsSyn Name) that serves as input to type checking.[2][35]
Type checking employs Haskell's Hindley-Milner (HM) type system for polymorphic type inference, generating type constraints from the renamed AST and solving them via unification to assign principal types to expressions and declarations. The process creates fresh type variables for unknowns, unifies them during inference (e.g., matching function argument and parameter types), and generalizes polymorphic types at let-bindings using let-generalization rules. For extensions like generalized algebraic data types (GADTs), the type checker integrates specialized unification that allows existential types and pattern-match refinements, ensuring type equality constraints are satisfied without full instantiation. Constraint solving handles type classes and instances through an external solver interface, supporting improvements like the OutsideIn(X) algorithm for better error localization. The output is a type-annotated AST (HsSyn Typechecked), with all types explicit and verified for consistency.[2][36]
Desugaring translates the type-checked Haskell AST into Core, a small, explicitly typed lambda calculus that serves as GHC's intermediate language for optimizations. This stage eliminates surface syntax sugar, such as converting do-notation for monads into bind operations (>>=), list comprehensions into applications of map and filter, and pattern guards into if-then-else constructs with guards. It also expands derived instances (e.g., for Eq or Show) and handles recursive definitions by introducing letrec bindings, resulting in a simplified, functional form without Haskell-specific idioms. The desugared Core retains type annotations and is positioned for the core-to-core optimization pipeline.[2]
Error reporting is integrated across frontend stages to provide actionable diagnostics, with the parser emitting syntax errors tied to token positions, the renamer highlighting scoping issues like undefined names or import conflicts, and the type checker generating detailed type mismatch explanations often including suggested fixes or hole-filled reports. Recent enhancements introduce a structured diagnostic framework using message envelopes for severity (error, warning) and categories, improving clarity and tool integration, such as in IDEs. All messages include source spans for precise location and leverage the AST for context-aware suggestions, minimizing user debugging effort.[2][37]
Core Language and Optimizations
The Core language in GHC is a simplified, explicitly typed functional intermediate representation derived from System F extended with type equality coercions, known as System FC. It features a small set of constructs including variables, literals, applications, lambda abstractions (both term and type), let expressions, and case expressions, enabling a clean foundation for applying optimizations. Desugared Haskell source code is translated into Core by the frontend, providing a uniform platform independent of surface syntax details. This design facilitates modular analysis and transformation, with types tracked explicitly to ensure correctness throughout the pipeline. GHC's optimization pipeline applies over 25 transformation passes to Core code, organized into iterative phases of the central simplifier module. These passes encompass inlining to eliminate function calls, lambda lifting to hoist nested lambdas to top-level bindings, common subexpression elimination to remove redundant computations, and strictness analysis to identify evaluation opportunities. Additional transformations include let-floating for better code layout, beta reduction for simplifying applications, and join-point analysis for optimizing recursive tail calls. The pipeline runs in multiple phases (typically four to two, decreasing iteratively), with each phase applying a sequence of rules to refine the code for efficiency, balancing compile-time cost against runtime performance gains.[38][39] Among the key techniques, the worker/wrapper transformation specializes functions by splitting them into a wrapper that handles boxed arguments and an unboxed worker that performs the core computation, enabling unboxing of primitive types like integers and floats to avoid heap allocation overhead. This is particularly effective for strict functions identified via demand analysis. List fusion, implemented through rewrite rules, optimizes data processing by composing producers and consumers; for example, the foldr/build rule fuses a list-building operation (using the genericbuild combinator) with a right fold (foldr), eliminating intermediate list allocations and reducing constant factors in time and space.[40][41]
Following Core optimizations, the transformed code is converted to the STG (Spineless Tagless G-machine) representation, an abstract graph reduction machine that models Haskell's lazy evaluation semantics without explicit tags on closures, simplifying garbage collection and runtime support. STG introduces low-level details like thunks and update frames while preserving the optimized structure from Core. For profiling and debugging, cost centers—markers for attributing execution costs to specific code regions—can be automatically inserted into Core during or after optimizations, with options like late insertion minimizing interference with passes such as inlining. This allows detailed runtime analysis, such as time and allocation profiling, without unduly compromising generated code quality.[42][43]
As a concrete example, consider fusing sum (a foldr over a list) with a list producer using build:
Without fusion, this generates an intermediate listsum = foldr (+) 0 xs = build (\c n -> ... ) []sum = foldr (+) 0 xs = build (\c n -> ... ) []
xs, allocating heap space. The foldr/build rule rewrites it directly to a loop over the builder's continuation c, avoiding the list entirely and fusing the operations into a single pass. This can yield asymptotic improvements for chained list transformations, as verified in GHC's rule application during simplification.[41][39]
Backend
The backend of the Glasgow Haskell Compiler (GHC) is responsible for transforming the optimized intermediate representation, known as Cmm (a variant of the C-- language), into executable machine code or other target formats. This phase handles low-level code generation, including instruction selection, register allocation, and platform-specific assembly output, ensuring efficient execution on diverse hardware. GHC supports multiple backends to balance compilation speed, code quality, and portability, with the native code generator serving as the default for most scenarios.[44][2] The Native Code Generator (NCG) directly compiles Cmm to assembly code for architectures such as x86, x86-64, ARM, AArch64, PowerPC, and others, producing native executables without external dependencies. It employs instruction selection to map Cmm operations to machine instructions, followed by register allocation using techniques like graph coloring or iterative coalescing to minimize spills and optimize performance. The NCG also applies peephole optimizations, which heuristically rewrite short instruction sequences for efficiency, such as eliminating redundant loads or reordering for better pipeline utilization. This backend excels in compilation speed and supports shared libraries effectively, making it suitable for production builds on supported platforms.[44][45][46] Cmm, derived from the C-- intermediate language, acts as a portable, low-level representation that bridges higher-level optimizations and final code emission, facilitating custom targets through its C-like syntax with explicit stack management and imperative constructs. This design enhances portability by abstracting architecture-specific details until the final generation step, allowing GHC to target new platforms with minimal changes to upstream components. While primarily internal, C-- enables extensions like alternative backends without overhauling the core pipeline.[2][45][47] Starting with version 7.0 in 2010, GHC has offered an optional LLVM backend that translates Cmm to LLVM intermediate representation for further optimization and code generation via the LLVM toolchain, often yielding superior performance in numeric and array-intensive workloads compared to the NCG. This integration requires LLVM versions 13 through 20 installed, including tools likeopt and llc, and is invoked with the -fllvm flag; it supports Linux, macOS, and Windows but incurs higher compilation overhead due to external processing. The backend leverages LLVM's advanced optimizations, such as vectorization, while preserving Haskell's semantics through careful handling of the runtime interface.[44][45][48]
For web development, GHC includes a JavaScript backend, evolved from the independent GHCJS project and merged into the mainline compiler in 2022, which compiles Haskell code to JavaScript while maintaining compatibility with GHC's core pipeline up to optimized STG intermediates. This allows Haskell applications to run in browsers, with ongoing support for features like Template Haskell in related WebAssembly targets.[49][50]
Final linking incorporates the Runtime System (RTS), a C-based component linked into every Haskell executable to manage essential services including a generational copying garbage collector for memory management, lightweight threading via a work-stealing scheduler for parallelism, and I/O operations. The RTS supports concurrent garbage collection options, such as the non-moving collector introduced in GHC 8.10, which reduces latency in threaded programs without requiring code changes beyond the -threaded flag. This setup ensures portability and efficiency across platforms, handling Haskell's non-strict evaluation model transparently.[2][51][52]
Language Implementation
Conformance to Haskell Standards
The Glasgow Haskell Compiler (GHC) aims to conform fully to the Haskell 2010 language standard, serving as its de facto reference implementation for core features, including modules, types, expressions, input/output (I/O), and the foreign function interface (FFI).[53][54] Modules in GHC adhere to the standard's specifications for export and import lists, instance declarations, and separate compilation, enabling modular program structure with abstract datatypes.[55] Type system conformance covers user-defined datatypes, type classes, overloading, and predefined types, ensuring type safety and inference as defined in the report.[56] Expressions follow the standard for variables, operators, lambda abstractions, pattern matching, and constructs like let, case, and do notation.[57] I/O operations conform to the IO monad semantics, including sequencing, exception handling, and file management via handles.[58] The FFI supports interoperability with foreign languages, particularly C, through declarations for external entities and data marshalling.[59] GHC retains partial support for the legacy Haskell 98 standard to maintain compatibility with older codebases, though it is deprecated in favor of Haskell 2010 and later editions.[53] This support includes the core syntax and semantics of Haskell 98 but omits some deprecated features, with GHC defaulting to Haskell 2010 mode unless explicitly configured otherwise.[53] For standard libraries, GHC's base package implements the Haskell 2010 Prelude and core modules, providing conformance for fundamental types, classes, and functions while flagging any GHC-specific additions or modifications through language pragmas. The base package ensures portability of standard I/O, numeric operations, and monadic structures across compliant implementations.[60] Compliance with Haskell standards is verified through GHC's comprehensive testsuite, which includes correctness tests for language features and library behaviors, alongside community-driven validation efforts to align with the official reports.[61] This testing infrastructure helps maintain adherence, though some infelicities persist. Known deviations from Haskell 2010 include variations in lazy evaluation strictness; for instance, GHC's implementation ofseq can eta-expand functions, potentially making certain error-handling cases more defined than specified, which can be adjusted via the -fpedantic-bottoms flag. In I/O, functions like hGetContents may throw exceptions on errors rather than discarding them silently, diverging from Haskell 98 but applicable in Haskell 2010 contexts. Standard library deviations encompass stricter evaluation in functions like splitAt and extended support for numeric literals in Read, such as hexadecimal formats. The FFI lacks support for re-initializing the runtime after hs_exit(), contrary to the addendum's expectations. These deviations are documented to guide users toward standard-compliant code.[53]
GHC also supports extensions beyond Haskell 2010 for advanced features, as covered in separate documentation.[53]
Extensions to Haskell
The Glasgow Haskell Compiler (GHC) extends the Haskell language through a flexible pragmas system that allows users to enable non-standard features on a per-module or global basis. This system supports two primary mechanisms: the LANGUAGE pragma, which can be placed at the top of a Haskell source file to activate specific extensions portably across compilers, and command-line flags prefixed with -X, such as -XOverloadedStrings, for project-wide or invocation-specific enabling.[53][62] Extensions like OverloadedStrings (which treats string literals as instances of the IsString typeclass for polymorphic string handling), BangPatterns (enabling strictness annotations in patterns with !), and RankNTypes (supporting higher-rank polymorphism via explicit forall quantifiers in types) exemplify this system's granularity, allowing developers to opt into enhanced expressiveness without altering core Haskell compliance.[63] GHC's extensions include several influential innovations in metaprogramming, type systems, and concurrency. Template Haskell, introduced in 2003, enables compile-time metaprogramming by allowing Haskell code to generate and splice other Haskell code during compilation, facilitating tasks like automated boilerplate derivation and domain-specific languages.[64] Generalized algebraic data types (GADTs), added in 2005, extend algebraic data types to support existential quantification and refined return types for constructors, enabling more precise type-safe representations such as typed expression evaluators.[65] Type families, available since 2007, introduce type-level functions that compute types from other types, supporting associated type families in classes for modular type computations like vector indexing or heterogeneous lists.[66] More recent extensions address advanced resource management and syntax ergonomics. Linear types, implemented in GHC 9.0 in 2021, introduce multiplicity tracking where linear arrows 1 -> require their argument to be used exactly once, enforced through static linearity checks during type inference and desugaring to ensure no accidental duplication or discarding of resources like file handles or GPU buffers.[67][68] Record dot syntax, stabilized in GHC 9.2 and enhanced in subsequent releases around 2023 via the OverloadedRecordDot extension, provides concise field access (e.g., person.name) by desugaring to getField calls, improving readability for large records while supporting overloaded projections.[69][70] GHC integrates Software Transactional Memory (STM) as a core concurrency primitive since version 6.4, providing atomic, composable transactions via the STM monad and combinators like atomically, retry, and orElse, which abstract shared state updates with automatic rollback on conflicts.[71][72] For parallelism, the -threaded flag activates runtime support for multicore execution, paired with strategies from the parallel package using par (to spark parallel evaluation) and combinators in the Eval monad, or the Par monad from monad-par for structured deterministic parallelism in computations like divide-and-conquer algorithms.[73][74] Extensions can be disabled individually with -fno-extension or via the NoExtension pragma, and recent GHC versions (9.0+) introduce language editions like GHC2021 and GHC2024, which bundle sensible defaults such as BangPatterns and TypeApplications for new projects, reducing boilerplate while maintaining opt-in control through flags or pragmas.[53][75] This ecosystem of extensions, managed via GhcFlags in build tools like Cabal, empowers Haskell programmers to balance expressiveness, safety, and performance beyond the Haskell 2010 standard.[76]Portability
Supported Platforms
The Glasgow Haskell Compiler (GHC) runs natively on a range of operating systems and architectures, categorized into support tiers that reflect the level of testing, maintenance, and official binary availability. Tier 1 platforms are fully tested via continuous integration and must function correctly for each release, ensuring reliable host environments for compiling Haskell code. These include x86-64 architectures on Linux (across major distributions such as Ubuntu 22.04+, Debian 12, Fedora 40+, Alpine 3.20+), macOS (version 12.0+ including Sonoma 14 and Sequoia 15), and 64-bit Windows (10/11).[77][78]| Tier | Platforms | Notes |
|---|---|---|
| 1 | x86-64 Linux, x86-64 macOS, x86-64 Windows, x86-64/AArch64 FreeBSD 13.x | Full CI testing; official binaries provided; primary focus for releases (as of GHC 9.12, 2025).[77][79] |
| 2 | AArch64 Linux, x86-64 FreeBSD 12.x, x86-64 OpenBSD, x86 Linux | Partial testing; functional with community maintenance; binaries available for some (e.g., AArch64 Linux on Debian 12, Alpine 3.20+); FreeBSD binaries as Tier 2 in GHC 9.14 (2025). 32-bit x86 Linux remains supported but deprecated in favor of 64-bit.[77][80] |
Cross-Compilation Capabilities
The Glasgow Haskell Compiler (GHC) enables cross-compilation, allowing Haskell code developed on a host system to be compiled for diverse target architectures and environments without requiring a native compiler on the target. This capability is essential for deploying Haskell applications to embedded systems, mobile devices, and web platforms, leveraging GHC's modular backend and toolchain configuration. Cross-compilation in GHC involves building a specialized version of the compiler configured for the desired target, which then generates executables or libraries compatible with that architecture.[83] GHC supports cross-compilation to several key architectures, including x86-64, AArch64 (ARM64), PowerPC, s390x, Tier 3 support for RISC-V (64-bit) since GHC 9.12 (2025), as well as WebAssembly via its native backend (introduced in GHC 9.6, with Template Haskell and GHCi support added in 9.10+ as of 2024–2025). For non-native targets, users must first build a cross-compiler using the./configure --target=<triple> script, where <triple> specifies the target (e.g., aarch64-unknown-linux-gnu for ARM64 Linux), followed by make to compile GHC itself for that target. This process requires a cross-toolchain, such as GCC or Clang configured for the target, to handle C dependencies and foreign function interfaces (FFI). Once built, the cross-compiler (often named like aarch64-linux-gnu-ghc) can be invoked directly or integrated with build tools like Cabal, using commands such as cabal configure --with-compiler=aarch64-linux-gnu-ghc to compile projects for the target, enabling workflows for platforms like Android and iOS through specialized setups that link against mobile SDKs. Recent improvements, such as the ghc-toolchain tool, simplify this by automating toolchain detection and configuration for common targets.[22][84][83][85][86]
Cross-compilation presents challenges, particularly in handling architecture-specific components like the runtime system (RTS), which must be ported or rebuilt for the target to manage memory and threading correctly, often requiring manual adjustments for new architectures. Foreign calls via FFI necessitate a matching cross-C compiler to link libraries, while endianness differences are addressed through target-specific code generation in GHC's backend. To support Template Haskell during cross-compilation, an external interpreter (iserv) must be built and deployed for the target, as the host compiler cannot execute target-specific splices directly. Solutions include using remote iserv proxies for mobile targets, allowing the host to orchestrate compilation while running target code in emulators.[83][87][88]
Practical examples demonstrate GHC's cross-compilation in action: for embedded systems like Raspberry Pi (AArch64), developers build a cross-GHC on x86 hosts and compile Haskell programs using standard Cabal workflows, linking against ARM toolchains for deployment. Mobile development, such as Haskell for Android, involves configuring GHC with Android NDK cross-compilers to produce shared libraries integrated into Java/Kotlin apps via JNI. For web environments, integration with GHCJS allows compilation to JavaScript, though the native WebAssembly backend in GHC provides a more direct path for browser-targeted executables, albeit experimentally as of 2025, with growing ecosystem integration including GHCi browser mode. Limitations include incomplete cross-compilation support for Windows targets from Unix-like hosts without Cygwin or MSYS2 environments, and ongoing experimental status for WebAssembly.[89][90]
Tools and Ecosystem
Interactive Environment (GHCi)
GHCi serves as the interactive read-eval-print loop (REPL) environment for the Glasgow Haskell Compiler (GHC), launched via theghci command-line tool. It functions primarily as a bytecode interpreter, allowing developers to load Haskell modules, evaluate expressions interactively, and interpret programs on the fly while supporting most GHC language extensions. Introduced with GHC version 6.0 in May 2003, GHCi has become essential for exploratory coding, rapid prototyping, and debugging in Haskell development.[91][92]
Key features of GHCi include direct expression evaluation at the prompt, where inputs like 1 + 2 immediately return 3, and support for IO actions such as putStrLn "hello". Type inspection is facilitated by the :type command, which infers and displays types—for instance, :type [length](/page/Length) yields [a] -> Int (or more generally, Foldable t => t a -> Int with extensions). The integrated debugger enables setting breakpoints via :break (e.g., :break 2 for line 2 of a module), single-stepping through reductions with :step, and variable inspection during pauses using :print or :force. Multi-shot evaluation allows handling nested contexts, with tools like :trace for step traces and :hist for evaluation history, enhancing traceability in complex sessions.[93][94]
GHCi compiles loaded modules to bytecode by default, a format optimized for quick interpretation and reloading during development, which contrasts with slower source-level evaluation. For performance gains—typically 10 to 20 times faster than bytecode—it can link pre-compiled object code using the -fobject-code or -dynamic flags, though this mode disables interactive debugging features like breakpoints and stepping.[95][96]
Customization options make GHCi adaptable to user workflows, including .ghci configuration files in the home directory or project root for loading modules or setting preferences on startup. Command history is managed with a configurable depth (default 50 via -fghci-hist-size), and editor integration is supported through :edit to open files at errors or via :set editor for custom tools. Prompt customization, such as :set prompt "%s> " (where %s inserts the current module), aids visibility in integrated development environments.[97][98]
Advanced capabilities include the statement monad for imperative-style interactions at the prompt, enabling do-notation sequences like x <- getLine; return (length x) that default to the IO monad. Profiling within the REPL is possible using the external interpreter mode (-fexternal-interpreter -prof), which generates stack traces and statistics for interpreted code, requiring profiled dependencies.[99][100]