GHC, Cabal, HLS, and Effect Systems for Professional Development
Introduction
Chapter 1: The Haskell Ecosystem Today
- Haskell in Production
- The Toolchain at a Glance
- Getting Started: Installing GHC and Cabal
- A Minimal Working Project
- The Development Loop
- Summary
Chapter 2: How GHC Compiles Your Code
- The Compilation Pipeline
- Core: GHC’s Intermediate Language
- The STG Machine and Register Allocation
- Code Generation and Object Files
- The Compilation Graph and Dependencies
- GHC Artifact Files: Hi, O, and Beyond
- Summary
Chapter 3: GHC’s Type System in Practice
- Types, Kinds, and the Kind System
- Type Classes: Structure and Resolution
- Essential Language Extensions
- Advanced Extensions: GADTs, DataKinds, TypeFamilies
- Type Error Diagnostics
- Type System Pitfalls and Anti-patterns
- Summary
Chapter 4: GHC Optimization and Compiler Flags
- Optimization Levels: -O, -O1, -O2
- Key Optimization Flags
- Profiling Flags and Their Interactions
- Development vs Production Build Configurations
- Inspecting Optimized Code with -ddump-simpl
- Optimization Gotchas: Float Invariants, Specialization
- Summary
Chapter 5: The GHC Runtime System
- The RTS Architecture
- Garbage Collection: Generational and Concurrent
- Lightweight Threads and the Scheduler
- Mutable State: MVars, TVars, STM
- RTS Flags and Configuration
- Memory Layout and Performance Implications
- Summary
Chapter 6: GHCi and Interactive Development
- GHCi Basics and Essential Commands
- Loading and Reloading Modules
- Interactive Debugging with Breakpoints and Stepping
- Script Mode and :! Commands
- GHCi Configuration and Startup Scripts
- Interactive Development Patterns
- Summary
Chapter 7: GHC Diagnostics and Warnings
- Warning Flags and Categories
- Essential Warnings for Production Code
- Configuring Warnings in Cabal and GHC Files
- Reading GHC Type Errors Systematically
- Common Error Patterns and Fixes
- Setting Up Your Project for Maximum Diagnostics
- Summary
Chapter 8: Cabal Package Management Fundamentals
- What a Cabal Package Is
- Package Description Format
- Dependencies and Version Constraints
- The Solver and Dependency Resolution
- Package Index and Hackage
- Cabal Config and Global Settings
- Summary
Chapter 9: Building Projects with Cabal
- Components: Libraries, Executables, Tests, Benchmarks
- Build Dependencies and Configuration
- Cabal Flags and Feature Management
- Build Scripts and Custom Setup
- Incremental Builds and Caching
- Build Output and Generated Files
- Summary
Chapter 10: Advanced Cabal: Large Projects and Multi-Package Sets
- Multi-Package Projects and Cabal Workspaces
- Local Package Dependencies and Path Constraints
- Solver Constraints and Pins
- Managing Dependencies Across Many Packages
- Splitting Large Projects: Library vs Application Boundaries
- Real-World Multi-Package Project Structures
- Summary
Chapter 11: Reproducible Builds, CI/CD, and Project Hygiene
- Reproducible Builds and Freezes
- Haskell Stack vs Cabal: When Each Makes Sense
- Continuous Integration for Haskell Projects
- Cross-Compilation and Platform-Specific Builds
- Documentation Generation with Haddock
- Keeping Dependencies Updated Safely
- Summary
Chapter 12: The Haskell Language Server
- What HLS Does and Why It Matters
- Installing and Configuring HLS
- Diagnostics and Real-Time Error Checking
- Code Completion and Navigation
- Code Actions and Refactoring
- Expression Evaluation and Hover Information
- Summary
Chapter 13: Editor Integration and HLS Workflows
- VS Code and haskell-vscode
- Neovim and HLS Integration
- Emacs and HLS Configuration
- Shared HLS Settings Across Editors
- HLS Performance Tuning for Large Projects
- Troubleshooting Common Editor Integration Issues
- Summary
Chapter 14: HLS Architecture and Internals
- The GHC API and HLS’s Use of It
- How HLS Parses and Type-Checks Your Code
- Caching and Incremental Processing
- The HLS Plugin System
- Performance Characteristics and Bottlenecks
- Extending HLS with Custom Plugins
- Summary
Chapter 15: Purity, Effects, and the IO Monad
- Purity and the No-Side-Effects Guarantee
- IO as a Computations Type, Not a Tag
- The Monad Abstraction
- Do Notation and Effect Sequencing
- Practical IO Patterns
- Summary
Chapter 16: Type Classes and Effect Abstraction
- Effect Abstraction via Type Classes
- The Hierarchy: Functor, Applicative, Monad
- MonadTrans and the Lifting Problem
- Common Effect Type Classes
- Designing Your Own Effect Classes
- When Effect Abstraction Helps and Hurts
- Summary
Chapter 17: Monad Transformers and MTL-Style Programming
- Monad Transformers: The Idea
- Common Transformers: ReaderT, StateT, ExceptT, WriterT
- Building Effect Stacks
- The MTL Pattern and Type Signatures
- ReaderT-Based Architectures for Services
- MTL Complexity and Maintenance Costs
- Summary
Chapter 18: Capability-Based Effects and Modern Patterns
- What Are Capabilities?
- Designing Capability-Based APIs
- The io-universe-family and Similar Approaches
- Testing with Capability-Based Designs
- Comparing Capabilities vs MTL
- Real-World Capability-Based Systems
- Summary
Chapter 19: Algebraic Effects and Freer Approaches
- Algebraic Effects: The Concept
- Free Monads and Freer Monads
- The extensible-effects Library
- Polysemy: Design and Trade-offs
- The effectful Library and Effect Handlers
- Choosing an Effects Library
- Summary
Chapter 20: Comparing Effect Systems and Choosing an Approach
- Evaluation Criteria for Effect Systems
- Direct IO vs Abstracted Effects
- MTL vs Capabilities vs Algebraic Effects: Head to Head
- Performance Comparison and Benchmarks
- Debugging and Observability Trade-offs
- Recommendations by Project Type and Size
- Summary
Chapter 21: Testing, Property Testing, and Quality Assurance
- Testing Philosophy in Haskell
- Unit Testing with Hspec
- Tasty as a Test Harness
- Property-Based Testing with QuickCheck
- Hedgehog: The Modern Alternative
- Integration Testing with Real Dependencies
- Summary
Chapter 22: Profiling, Benchmarking, and Performance Tuning
- CPU Profiling with -prof and -auto-all
- Reading GHC Profile Output
- Memory and Heap Profiling
- Runtime Statistics and RTS Reporting
- Benchmarking with Criterion
- Performance Tuning Strategies
- Summary
Chapter 23: Debugging, Observability, and Production Practices
- Debugging Strategies in a Pure Language
- Logging Architectures for Haskell Services
- Tracing and OpenTelemetry Integration
- Handling Errors and Failures Gracefully
- Production Configuration and Health Checks
- Incident Response for Haskell Services
- Summary
Chapter 24: Troubleshooting Case Studies
- Dependency Resolution Failures
- Confusing Type Errors: A Methodical Approach
- Compilation Errors from Missing Extensions and Flags
- HLS Not Working: Common Causes and Fixes
- Slow Compilation: Diagnosis and Remedies
- Runtime Crashes and Memory Issues
- Summary
Chapter 25: Conclusion: The Future of Haskell Tooling
- What Has Changed in the Last Decade
- Ongoing Work in GHC
- The Cabal and Build System Future
- HLS and Developer Experience
- Effect Systems: Where the Ecosystem Is Heading
- Haskell in the Professional Landscape