Front cover image for Real world Haskell

Real world Haskell

This easy-to-use, fast-moving tutorial introduces you to functional programming with Haskell. You'll learn how to use Haskell in a variety of practical ways, from short scripts to large and demanding applications. Real World Haskell takes you through the basics of functional programming at a brisk pace, and then helps you increase your understanding of Haskell in real-world issues like I/O, performance, dealing with data, concurrency, and more as you move through each chapter
eBook, English, 2009
First edition View all formats and editions
O'Reilly, Sebastopol, California, 2009
1 online resource (711 pages)
9780596554309, 0596554303
1300559303
Intro
Table of Contents
Preface
Have We Got a Deal for You!
Novelty
Power
Enjoyment
What to Expect from This Book
A Little Bit About You
What to Expect from Haskell
Compared to Traditional Static Languages
Compared to Modern Dynamic Languages
Haskell in Industry and Open Source
Compilation, Debugging, and Performance Analysis
Bundled and Third-Party Libraries
A Brief Sketch of Haskell's History
Prehistory
Early Antiquity
The Modern Era
Helpful Resources
Reference Material
Applications and Libraries
The Haskell Community
Conventions Used in This Book
Using Code Examples
Safari® Books Online
How to Contact Us
Acknowledgments
Bryan
John
Don
Thank You to Our Reviewers
Chapter 1. Getting Started
Your Haskell Environment
Getting Started with ghci, the Interpreter
Basic Interaction: Using ghci as a Calculator
Simple Arithmetic
An Arithmetic Quirk: Writing Negative Numbers
Boolean Logic, Operators, and Value Comparisons
Operator Precedence and Associativity
Undefined Values, and Introducing Variables
Dealing with Precedence and Associativity Rules
Command-Line Editing in ghci
Lists
Operators on Lists
Strings and Characters
First Steps with Types
A Simple Program
Chapter 2. Types and Functions
Why Care About Types?
Haskell's Type System
Strong Types
Static Types
Type Inference
What to Expect from the Type System
Some Common Basic Types
Function Application
Useful Composite Data Types: Lists and Tuples
Functions over Lists and Tuples
Passing an Expression to a Function
Function Types and Purity
Haskell Source Files, and Writing Simple Functions
Just What Is a Variable, Anyway?
Conditional Evaluation
Understanding Evaluation by Example
Lazy Evaluation. A More Involved Example
Recursion
Ending the Recursion
Returning from the Recursion
What Have We Learned?
Polymorphism in Haskell
Reasoning About Polymorphic Functions
Further Reading
The Type of a Function of More Than One Argument
Why the Fuss over Purity?
Conclusion
Chapter 3. Defining Types, Streamlining Functions
Defining a New Data Type
Naming Types and Values
Type Synonyms
Algebraic Data Types
Tuples, Algebraic Data Types, and When to Use Each
Analogues to Algebraic Data Types in Other Languages
The structure
The enumeration
The discriminated union
Pattern Matching
Construction and Deconstruction
Further Adventures
Variable Naming in Patterns
The Wild Card Pattern
Exhaustive Patterns and Wild Cards
Record Syntax
Parameterized Types
Recursive Types
Reporting Errors
A More Controlled Approach
Introducing Local Variables
Shadowing
The where Clause
Local Functions, Global Variables
The Offside Rule and Whitespace in an Expression
A Note About Tabs Versus Spaces
The Offside Rule Is Not Mandatory
The case Expression
Common Beginner Mistakes with Patterns
Incorrectly Matching Against a Variable
Incorrectly Trying to Compare for Equality
Conditional Evaluation with Guards
Chapter 4. Functional Programming
Thinking in Haskell
A Simple Command-Line Framework
Warming Up: Portably Splitting Lines of Text
A Line-Ending Conversion Program
Infix Functions
Working with Lists
Basic List Manipulation
Safely and Sanely Working with Crashy Functions
Partial and Total Functions
More Simple List Manipulations
Working with Sublists
Searching Lists
Working with Several Lists at Once
Special String-Handling Functions
How to Think About Loops
Explicit Recursion. Transforming Every Piece of Input
Mapping over a List
Selecting Pieces of Input
Computing One Answer over a Collection
The Left Fold
Why Use Folds, Maps, and Filters?
Folding from the Right
Left Folds, Laziness, and Space Leaks
Further Reading
Anonymous (lambda) Functions
Partial Function Application and Currying
Sections
As-patterns
Code Reuse Through Composition
Use Your Head Wisely
Tips for Writing Readable Code
Space Leaks and Strict Evaluation
Avoiding Space Leaks with seq
Learning to Use seq
Chapter 5. Writing a Library: Working with JSON Data
A Whirlwind Tour of JSON
Representing JSON Data in Haskell
The Anatomy of a Haskell Module
Compiling Haskell Source
Generating a Haskell Program and Importing Modules
Printing JSON Data
Type Inference Is a Double-Edged Sword
A More General Look at Rendering
Developing Haskell Code Without Going Nuts
Pretty Printing a String
Arrays and Objects, and the Module Header
Writing a Module Header
Fleshing Out the Pretty-Printing Library
Compact Rendering
True Pretty Printing
Following the Pretty Printer
Creating a Package
Writing a Package Description
GHC's Package Manager
Setting Up, Building, and Installing
Practical Pointers and Further Reading
Chapter 6. Using Typeclasses
The Need for Typeclasses
What Are Typeclasses?
Declaring Typeclass Instances
Important Built-in Typeclasses
Show
Read
Serialization with read and show
Numeric Types
Equality, Ordering, and Comparisons
Automatic Derivation
Typeclasses at Work: Making JSON Easier to Use
More Helpful Errors
Making an Instance with a Type Synonym
Living in an Open World
When Do Overlapping Instances Cause Problems?
Relaxing Some Restrictions on Typeclasses
How Does Show Work for Strings?. How to Give a Type a New Identity
Differences Between Data and Newtype Declarations
Summary: The Three Ways of Naming Types
JSON Typeclasses Without Overlapping Instances
The Dreaded Monomorphism Restriction
Conclusion
Chapter 7. I/O
Classic I/O in Haskell
Pure Versus I/O
Why Purity Matters
Working with Files and Handles
More on openFile
Closing Handles
Seek and Tell
Standard Input, Output, and Error
Deleting and Renaming Files
Temporary Files
Extended Example: Functional I/O and Temporary Files
Lazy I/O
hGetContents
readFile and writeFile
A Word on Lazy Output
interact
Filters with interact
The IO Monad
Actions
Sequencing
The True Nature of Return
Is Haskell Really Imperative?
Side Effects with Lazy I/O
Buffering
Buffering Modes
Flushing The Buffer
Reading Command-Line Arguments
Environment Variables
Chapter 8. Efficient File Processing, Regular Expressions, and Filename Matching
Efficient File Processing
Binary I/O and Qualified Imports
Text I/O
Filename Matching
Regular Expressions in Haskell
The Many Types of Result
More About Regular Expressions
Mixing and Matching String Types
Other Things You Should Know
Translating a glob Pattern into a Regular Expression
An important Aside: Writing Lazy Functions
Making Use of Our Pattern Matcher
Handling Errors Through API Design
Putting Our Code to Work
Chapter 9. I/O Case Study: A Library for Searching the Filesystem
The find Command
Starting Simple: Recursively Listing a Directory
Revisiting Anonymous and Named Functions
Why Provide Both mapM and forM?
A Naive Finding Function
Predicates: From Poverty to Riches, While Remaining Pure
Sizing a File Safely
The Acquire-Use-Release Cycle
A Domain-Specific Language for Predicates. Avoiding Boilerplate with Lifting
Gluing Predicates Together
Defining and Using New Operators
Controlling Traversal
Density, Readability, and the Learning Process
Another Way of Looking at Traversal
Useful Coding Guidelines
Common Layout Styles
Chapter 10. Code Case Study: Parsing a Binary Data Format
Grayscale Files
Parsing a Raw PGM File
Getting Rid of Boilerplate Code
Implicit State
The Identity Parser
Record Syntax, Updates, and Pattern Matching
A More Interesting Parser
Obtaining and Modifying the Parse State
Reporting Parse Errors
Chaining Parsers Together
Introducing Functors
Constraints on Type Definitions Are Bad
Infix Use of fmap
Flexible Instances
Thinking More About Functors
Writing a Functor Instance for Parse
Using Functors for Parsing
Rewriting Our PGM Parser
Future Directions
Chapter 11. Testing and Quality Assurance
QuickCheck: Type-Based Testing
Testing for Properties
Testing Against a Model
Testing Case Study: Specifying a Pretty Printer
Generating Test Data
Testing Document Construction
Using Lists as a Model
Putting It All Together
Measuring Test Coverage with HPC
Chapter 12. Barcode Recognition
A Little Bit About Barcodes
EAN-13 Encoding
Introducing Arrays
Arrays and Laziness
Folding over Arrays
Modifying Array Elements
Encoding an EAN-13 Barcode
Constraints on Our Decoder
Divide and Conquer
Turning a Color Image into Something Tractable
Parsing a Color Image
Grayscale Conversion
Grayscale to Binary and Type Safety
What Have We Done to Our Image?
Finding Matching Digits
Run Length Encoding
Scaling Run Lengths, and Finding Approximate Matches
List Comprehensions
Remembering a Match's Parity
Another kind of laziness, of the keyboarding variety
Includes index
Chunking a List