Haskell in Depth

Book description

Turn the corner from “Haskell student” to “Haskell developer.” Haskell in Depth explores the important language features and programming skills you’ll need to build production-quality software using Haskell. And along the way, you’ll pick up some interesting insights into why Haskell looks and works the way it does. Get ready to go deep!

About the Technology
Software for high-precision tasks like financial transactions, defense systems, and scientific research must be absolutely, provably correct. As a purely functional programming language, Haskell enforces a mathematically rigorous approach that can lead to concise, efficient, and bug-free code. To write such code you’ll need deep understanding. You can get it from this book!

About the Book
Haskell in Depth unlocks a new level of skill with this challenging language. Going beyond the basics of syntax and structure, this book opens up critical topics like advanced types, concurrency, and data processing. You’ll discover key parts of the Haskell ecosystem and master core design patterns that will transform how you write software.

What's Inside
  • Building applications, web services, and networking apps
  • Using sophisticated libraries like lens, singletons, and servant
  • Organizing projects with Cabal and Stack
  • Error-handling and testing
  • Pure parallelism for multicore processors


About the Reader
For developers familiar with Haskell basics.

About the Author
Vitaly Bragilevsky has been teaching Haskell and functional programming since 2008. He is a member of the GHC Steering Committee.

Quotes
A clearly written guide. It’ll take your Haskell skills beyond the ‘getting started’ level.
- Phillip Sorensen, Cornell University

Packed full of practical knowledge to level up your design skills.
- Jose Luis Garcia, Nielsen

A practical book for real-world Haskell programs. It expands your Haskell knowledge to new frontiers.
- David Paccoud, Bioclinica

One of the most richly-detailed books on programming that I’ve encountered. Rewarding on many levels.
- Charles Earl, Automattic

Publisher resources

View/Submit Errata

Table of contents

  1. Haskell in Depth
  2. Copyright
  3. dedication
  4. brief contents
  5. contents
  6. front matter
    1. foreword
    2. preface
      1. Functional programming
      2. Type system
      3. Lazy evaluation
      4. Tooling around Haskell
      5. What can be done using Haskell: Libraries
    3. acknowledgments
    4. about this book
      1. Who should read this book
      2. How this book is organized: A roadmap
      3. About the code
      4. Getting the sources
      5. Using cabal
      6. Using stack
      7. liveBook discussion forum
    5. about the author
    6. about the cover illustration
  7. Part 1. Core Haskell
  8. 1 Functions and types
    1. 1.1 Solving problems in the GHCi REPL with functions
    2. 1.2 From GHCi and String to GHC and Text
    3. 1.3 Functional programs as sets of IO actions
    4. 1.4 Embracing pure functions
      1. 1.4.1 Separating I/O from pure functions
      2. 1.4.2 Computing the most frequent words by sorting them
      3. 1.4.3 Formatting reports
      4. 1.4.4 Rule them all with IO actions
      5. Summary
  9. 2 Type classes
    1. 2.1 Manipulating a radar antenna with type classes
      1. 2.1.1 The problem at hand
      2. 2.1.2 Rotating a radar antenna with Eq, Enum, and Bounded
      3. 2.1.3 Combining turns with Semigroup and Monoid
      4. 2.1.4 Printing and reading data with Show and Read
      5. 2.1.5 Testing functions with Ord and Random
    2. 2.2 Issues with numbers and text
      1. 2.2.1 Numeric types and type classes
      2. 2.2.2 Numeric conversions
      3. 2.2.3 Computing with fixed precision
      4. 2.2.4 More about Show and Read
      5. 2.2.5 Converting recursive types to strings
    3. 2.3 Abstracting computations with type classes
      1. 2.3.1 An idea of a computational context and a common behavior
      2. 2.3.2 Exploring different contexts in parallel
      3. 2.3.3 The do notation
      4. 2.3.4 Folding and traversing
      5. Summary
  10. 3 Developing an application: Stock quotes
    1. 3.1 Setting the scene
      1. 3.1.1 Inputs
      2. 3.1.2 Outputs
      3. 3.1.3 Project structure
    2. 3.2 Exploring design space
      1. 3.2.1 Designing the user interface
      2. 3.2.2 Dealing with input data
      3. 3.2.3 Formatting reports
      4. 3.2.4 Plotting charts
      5. 3.2.5 Project dependencies overview
    3. 3.3 Implementation details
      1. 3.3.1 Describing data
      2. 3.3.2 Plotting charts
      3. 3.3.3 Preparing reports
      4. 3.3.4 Implementing the user interface
      5. 3.3.5 Connecting parts
    4. Summary
  11. Part 2. Introduction to application design
  12. 4 Haskell development with modules, packages, and projects
    1. 4.1 Organizing Haskell code with modules
      1. 4.1.1 Module structure, imports and exports, and module hierarchy
      2. 4.1.2 Custom Preludes
      3. 4.1.3 Example: containers-mini
    2. 4.2 Understanding Haskell packages
      1. 4.2.1 Packages at the GHC level
      2. 4.2.2 Cabal packages and Hackage
    3. 4.3 Tools for project development
      1. 4.3.1 Dependency management
      2. 4.3.2 Haskell projects as a collection of packages
      3. 4.3.3 Common project management activities and tools
      4. Summary
  13. 5 Monads as practical functionality providers
    1. 5.1 Basic monads in use: Maybe, Reader, Writer
      1. 5.1.1 Maybe monad as a line saver
      2. 5.1.2 Carrying configuration all over the program with Reader
      3. 5.1.3 Writing logs via Writer
    2. 5.2 Maintaining state via the State monad
      1. 5.2.1 Basic examples with the State monad
      2. 5.2.2 Parsing arithmetic expressions with State
      3. 5.2.3 RWS monad to rule them all: The game of dice
    3. 5.3 Other approaches to mutability
      1. 5.3.1 Mutable references in the IO monad
      2. 5.3.2 Mutable references in the ST monad
    4. Summary
  14. 6 Structuring programs with monad transformers
    1. 6.1 The problem of combining monads
      1. 6.1.1 Evaluating expressions in reverse Polish notation
      2. 6.1.2 Introducing monad transformers and monad stacks
    2. 6.2 IO-based monad transformer stacks
      1. 6.2.1 Describing a monad stack
      2. 6.2.2 Exploiting monad stack functionality
      3. 6.2.3 Running an application
      4. 6.2.4 Can we do it without RWST?
    3. 6.3 What is a monad transformer?
      1. 6.3.1 Step 0: Defining a type for a transformer
      2. 6.3.2 Step 1: Turning a monad stack into a monad
      3. 6.3.3 Step 2: Implementing the full monad stack functionality
      4. 6.3.4 Step 3: Supplying additional functionality
      5. 6.3.5 Using a transformer
    4. 6.4 Monad transformers in the Haskell libraries
      1. 6.4.1 Identity is where it all starts
      2. 6.4.2 An overview of the most common monad transformers
    5. Summary
  15. Part 3. Quality assurance
  16. 7 Error handling and logging
    1. 7.1 Overview of error-handling mechanisms in Haskell
      1. 7.1.1 The idea of exceptions
      2. 7.1.2 To use or not to use?
      3. 7.1.3 Programmable exceptions vs. GHC runtime exceptions
    2. 7.2 Programmable exceptions in monad stacks
      1. 7.2.1 The ExceptT monad transformer
      2. 7.2.2 Example: Evaluating RPN expressions
    3. 7.3 GHC runtime exceptions
      1. 7.3.1 An idea of extensible exceptions
      2. 7.3.2 Throwing exceptions
      3. 7.3.3 Catching exceptions
    4. 7.4 Example: Accessing web APIs and GHC exceptions
      1. 7.4.1 Application components
      2. 7.4.2 Exception-handling strategies
    5. 7.5 Logging
      1. 7.5.1 An overview of the monad-logger library
      2. 7.5.2 Introducing logging with monad-logger into the suntimes project
      3. Summary
  17. 8 Writing tests
    1. 8.1 Setting a scene: IPv4 filtering application
      1. 8.1.1 Development process overview
      2. 8.1.2 Initial implementation
    2. 8.2 Testing the IPv4 filtering application
      1. 8.2.1 Overview of approaches to testing
      2. 8.2.2 Testing Cabal projects with tasty
      3. 8.2.3 Specifications writing and checking with Hspec
      4. 8.2.4 Property-based testing with Hedgehog
      5. 8.2.5 Golden tests with tasty-golden
    3. 8.3 Other approaches to testing
      1. 8.3.1 Testing functions à la the REPL with doctest
      2. 8.3.2 Lightweight verification with LiquidHaskell
      3. 8.3.3 Code quality with hlint
      4. Summary
  18. 9 Haskell data and code at run time
    1. 9.1 A mental model for Haskell memory usage at run time
      1. 9.1.1 General memory structure and closures
      2. 9.1.2 Primitive unboxed data types
      3. 9.1.3 Representing data and code in memory with closures
      4. 9.1.4 A detour: Lifted types and the concept of strictness
    2. 9.2 Control over evaluation and memory usage
      1. 9.2.1 Controlling strictness and laziness
      2. 9.2.2 Defining data types with unboxed values
    3. 9.3 Exploring compiler optimizations by example
      1. 9.3.1 Optimizing code manually
      2. 9.3.2 Looking at GHC Core
    4. Summary
  19. 10 Benchmarking and profiling
    1. 10.1 Benchmarking functions with criterion
      1. 10.1.1 Benchmarking implementations of a simple function
      2. 10.1.2 Benchmarking an IPv4 filtering application
    2. 10.2 Profiling execution time and memory usage
      1. 10.2.1 Simulating iplookup usage in the real world
      2. 10.2.2 Analyzing execution time and memory allocation
      3. 10.2.3 Analyzing memory usage
    3. 10.3 Tuning performance of the IPv4 filtering application
      1. 10.3.1 Choosing the right data structure
      2. 10.3.2 Squeezing parseIP performance
    4. Summary
  20. Part 4. Advanced Haskell
  21. 11 Type system advances
    1. 11.1 Haskell types 101
      1. 11.1.1 Terms, types, and kinds
      2. 11.1.2 Delivering information with types
      3. 11.1.3 Type operators
    2. 11.2 Data kinds and type-level literals
      1. 11.2.1 Promoting types to kinds and values to types
      2. 11.2.2 Type-level literals
    3. 11.3 Computations over types with type families
      1. 11.3.1 Open and closed type synonym families
      2. 11.3.2 Example: Avoid character escaping in GHCi
      3. 11.3.3 Data families
      4. 11.3.4 Associated families
    4. 11.4 Generalized algebraic data types
      1. 11.4.1 Example: Representing dynamically typed values with GADTs
      2. 11.4.2 Example: Representing arithmetic expressions with GADTs
    5. 11.5 Arbitrary-rank polymorphism
      1. 11.5.1 The meaning
      2. 11.5.2 Use cases
    6. 11.6 Advice on dealing with type errors
      1. 11.6.1 Be explicit about types
      2. 11.6.2 Ask the compiler
      3. 11.6.3 Saying more about errors
      4. Summary
  22. 12 Metaprogramming in Haskell
    1. 12.1 Deriving instances
      1. 12.1.1 Basic deriving strategies
      2. 12.1.2 The problem of type safety and generalized newtype deriving
      3. 12.1.3 Deriving by an example with DerivingVia
    2. 12.2 Data-type-generic programming
      1. 12.2.1 Generic data-type representation
      2. 12.2.2 Example: Generating SQL queries
    3. 12.3 Template Haskell and quasiquotes
      1. 12.3.1 A tutorial on Template Haskell
      2. 12.3.2 Example: Generating remote function calls
    4. Summary
  23. 13 More about types
    1. 13.1 Types for specifying a web API
      1. 13.1.1 Implementing a web API from scratch
      2. 13.1.2 Implementing a web service with servant
    2. 13.2 Toward dependent types with singletons
      1. 13.2.1 Safety in Haskell programs
      2. 13.2.2 Example: Unsafe interface for elevators
      3. 13.2.3 Dependent types and substituting them with singletons
      4. 13.2.4 Example: Safe interface for elevators
      5. Summary
  24. Part 5. Haskell toolkit
  25. 14 Data-processing pipelines
    1. 14.1 Streaming data
      1. 14.1.1 General components and naive implementation
      2. 14.1.2 The streaming package
    2. 14.2 Approaching an implementation of pipeline stages
      1. 14.2.1 Reading and writing data efficiently
      2. 14.2.2 Parsing data with parser combinators
      3. 14.2.3 Accessing data with lenses
    3. 14.3 Example: Processing COVID-19 data
      1. 14.3.1 The task
      2. 14.3.2 Processing data
      3. 14.3.3 Organizing the pipeline
      4. Summary
  26. 15 Working with relational databases
    1. 15.1 Setting up an example
      1. 15.1.1 Sample database
      2. 15.1.2 Sample queries
      3. 15.1.3 Data representation in Haskell
    2. 15.2 Haskell database connectivity
      1. 15.2.1 Connecting to a database
      2. 15.2.2 Relating Haskell data types to database types
      3. 15.2.3 Constructing and executing SELECT queries
      4. 15.2.4 Manipulating data in a database
      5. 15.2.5 Solving tasks by issuing many queries
    3. 15.3 The postgresql-simple library
      1. 15.3.1 Connecting to a database
      2. 15.3.2 Relating Haskell data types to database types
      3. 15.3.3 Executing queries
    4. 15.4 The hasql ecosystem
      1. 15.4.1 Structuring programs with hasql
      2. 15.4.2 Constructing type-safe SQL statements
      3. 15.4.3 Implementing database sessions
      4. 15.4.4 Running database sessions
      5. 15.4.5 The need for low-level operations and decoding data manually
    5. 15.5 Generating SQL with opaleye
      1. 15.5.1 Structuring programs with opaleye
      2. 15.5.2 Describing database tables and their fields
      3. 15.5.3 Writing queries
      4. 15.5.4 Running queries
    6. Summary
  27. 16 Concurrency
    1. 16.1 Running computations concurrently
      1. 16.1.1 An implementation of concurrency in GHC
      2. 16.1.2 Low-level concurrency with threads
      3. 16.1.3 High-level concurrency with the async package
    2. 16.2 Synchronization and communication
      1. 16.2.1 Synchronized mutable variables and channels
      2. 16.2.2 Software transactional memory (STM)
    3. Summary
  28. appendix Further reading
    1. Books
    2. Research papers
  29. index

Product information

  • Title: Haskell in Depth
  • Author(s): Vitaly Bragilevsky
  • Release date: June 2021
  • Publisher(s): Manning Publications
  • ISBN: 9781617295409