真实世界的Haskell(影印版)
目 录内容简介
Preface
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…
查看完整
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…
查看完整
目 录内容简介
Haskell is most likely quite different from any language youve ever used before. Compared to the usual set of concepts in a programmers mental toolbox, functional programming offers us a profoundly different way to think about software.
In Haskell, we deemphasize code that modifies data. Instead, we focus on functions that take immutable values as input and produce new values as output. Given the …
查看完整
In Haskell, we deemphasize code that modifies data. Instead, we focus on functions that take immutable values as input and produce new values as output. Given the …
查看完整
目 录内容简介
Preface
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Chunking a List
Generating a List of Candidate Digits
Life Without Arrays or Hash Tables
A Forest of Solutions
A Brief Introduction to Maps
Further Reading
Turning Digit Soup into an Answer
Solving for Check Digits in Parallel
Completing the Solution Map with the First Digit
Finding the Correct Sequence
Working with Row Data
Pulling It All Together
A Few Comments on Development Style
13. Data Structures
Association Lists
Maps
Functions Are Data, Too
Extended Example: /etc/passwd
Extended Example: Numeric Types
First Steps
Completed Code
Taking Advantage of Functions as Data
Turning Difference Lists into a Proper Library
Lists, Difference Lists, and Monoids
General-Purpose Sequences
14. Monads
Revisiting Earlier Code Examples
Maybe Chaining
Implicit State
Looking for Shared Patterns
The Monad Typeclass
And Now, a Jargon Moment
Using a New Monad: Show Your Work!
Information Hiding
Controlled Escape
Leaving a Trace
Using the Logger Monad
Mixing Pure and Monadic Code
Putting a Few Misconceptions to Rest
Building the Logger Monad
Sequential Logging, Not Sequential Evaluation
The Writer Monad
The Maybe Monad
Executing the Maybe Monad
Maybe at Work, and Good API Design
The List Monad
Understanding the List Monad
Putting the List Monad to Work
Desugaring of do Blocks
Monads as a Programmable Semicolon
Why Go Sugar-Free?
The State Monad
Almost a State Monad
Reading and Modifying the State
Will the Real State Monad Please Stand Up?
Using the State Monad: Generating Random Values
A First Attempt at Purity
Random Values in the State Monad
Running the State Monad
What About a Bit More State?
Monads and Functors
Another Way of Looking at Monads
The Monad Laws and Good Coding Style
15. Programming with Monads
Golfing Practice: Association Lists
Generalized Lifting
Looking for Alternatives
The Name mplus Does Not Imply Addition
Rules for Working with MonadPlus
Failing Safely with MonadPlus
Adventures in Hiding the Plumbing
Supplying Random Numbers
Another Round of Golf
Separating Interface from Implementation
Multiparameter Typeclasses
Functional Dependencies
Rounding Out Our Module
Programming to a Monad’s Interface
The Reader Monad
A Return to Automated Deriving
Hiding the IO Monad
Using a newtype
Designing for Unexpected Uses
Using Typeclasses
Isolation and Testing
The Writer Monad and Lists
Arbitrary I/O Revisited
16. Using Parsec
First Steps with Parsec: Simple CSV Parsing
The sepBy and endBy Combinators
Choices and Errors
Lookahead
Error Handling
Extended Example: Full CSV Parser
Parsec and MonadPlus
Parsing a URL-Encoded Query String
Supplanting Regular Expressions for Casual Parsing
Parsing Without Variables
Applicative Functors for Parsing
Applicative Parsing by Example
Parsing JSON Data
Parsing a HTTP Request
Backtracking and Its Discontents
Parsing Headers
17. Interfacing with C: The FFI
Foreign Language Bindings: The Basics
Be Careful of Side Effects
A High-Level Wrapper
Regular Expressions for Haskell: A Binding for PCRE
Simple Tasks: Using the C Preprocessor
Binding Haskell to C with hsc2hs
Adding Type Safety to PCRE
Binding to Constants
Automating the Binding
Passing String Data Between Haskell and C
Typed Pointers
Memory Management: Let the Garbage Collector Do the Work
A High-Level Interface: Marshaling Data
Marshaling ByteStrings
Allocating Local C Data: The Storable Class
Putting It All Together
Matching on Strings
Extracting Information About the Pattern
Pattern Matching with Substrings
The Real Deal: Compiling and Matching Regular Expressions
18. Monad Transformers
Motivation: Boilerplate Avoidance
A Simple Monad Transformer Example
Common Patterns in Monads and Monad Transformers
Stacking Multiple Monad Transformers
Hiding Our Work
Moving Down the Stack
When Explicit Lifting Is Necessary
Understanding Monad Transformers by Building One
Creating a Monad Transformer
More Typeclass Instances
Replacing the Parse Type with a Monad Stack
Transformer Stacking Order Is Important
Putting Monads and Monad Transformers into Perspective
Interference with Pure Code
Overdetermined Ordering
Runtime Overhead
Unwieldy Interfaces
Pulling It All Together
19. Error Handling
Error Handling with Data Types
Use of Maybe
Use of Either
Exceptions
First Steps with Exceptions
Laziness and Exception Handling
Using handle
Selective Handling of Exceptions
I/O Exceptions
Throwing Exceptions
Dynamic Exceptions
Error Handling in Monads
A Tiny Parsing Framework
20. Systems Programming in Haskell
Running External Programs
Directory and File Information
Program Termination
Dates and Times
ClockTime and CalendarTime
File Modification Times
Extended Example: Piping
Using Pipes for Redirection
Better Piping
Final Words on Pipes
21. Using Databases
Overview of HDBC
Installing HDBC and Drivers
Connecting to Databases
Transactions
Simple Queries
SqlValue
Query Parameters
Prepared Statements
Reading Results
Reading with Statements
Lazy Reading
Database Metadata
Error Handling
22. Extended Example: Web Client Programming
Basic Types
The Database
The Parser
Downloading
Main Program
23. GUI Programming with gtk2hs
Installing gtk2hs
Overview of the GTK+ Stack
User Interface Design with Glade
Glade Concepts
Event-Driven Programming
Initializing the GUI
The Add Podcast Window
Long-Running Tasks
Using Cabal
24. Concurrent and Multicore Programming
Defining Concurrency and Parallelism
Concurrent Programming with Threads
Threads Are Nondeterministic
Hiding Latency
Simple Communication Between Threads
The Main Thread and Waiting for Other Threads
Safely Modifying an MVar
Safe Resource Management: A Good Idea, and Easy Besides
Finding the Status of a Thread
Writing Tighter Code
Communicating over Channels
Useful Things to Know About
MVar and Chan Are Nonstrict
Chan Is Unbounded
Shared-State Concurrency Is Still Hard
Deadlock
Starvation
Is There Any Hope?
Using Multiple Cores with GHC
Runtime Options
Finding the Number of Available Cores from Haskell
Choosing the Right Runtime
Parallel Programming in Haskell
Normal Form and Head Normal Form
Sequential Sorting
Transforming Our Code into Parallel Code
Knowing What to Evaluate in Parallel
What Promises Does par Make?
Running Our Code and Measuring Performance
Tuning for Performance
Parallel Strategies and MapReduce
Separating Algorithm from Evaluation
Separating Algorithm from Strategy
Writing a Simple MapReduce Definition
MapReduce and Strategies
Sizing Work Appropriately
Efficiently Finding Line-Aligned Chunks
Counting Lines
Finding the Most Popular URLs
Conclusions
25. Profiling and Optimization
Profiling Haskell Programs
Collecting Runtime Statistics
Time Profiling
Space Profiling
Controlling Evaluation
Strictness and Tail Recursion
Adding Strictness
Understanding Core
Advanced Techniques: Fusion
Tuning the Generated Assembly
Conclusions
26. Advanced Library Design: Building a Bloom Filter
Introducing the Bloom Filter
Use Cases and Package Layout
Basic Design
Unboxing, Lifting, and Bottom
The ST Monad
Designing an API for Qualified Import
Creating a Mutable Bloom Filter
The Immutable API
Creating a Friendly Interface
Re-Exporting Names for Convenience
Hashing Values
Turning Two Hashes into Many
Implementing the Easy Creation Function
Creating a Cabal Package
Dealing with Different Build Setups
Compilation Options and Interfacing to C
Testing with QuickCheck
Polymorphic Testing
Writing Arbitrary Instances for ByteStrings
Are Suggested Sizes Correct?
Performance Analysis and Tuning
Profile-Driven Performance Tuning
27. Sockets and Syslog
Basic Networking
Communicating with UDP
UDP Client Example: syslog
UDP Syslog Server
Communicating with TCP
Handling Multiple TCP Streams
TCP Syslog Server
TCP Syslog Client
28. Software Transactional Memory
The Basics
Some Simple Examples
STM and Safety
Retrying a Transaction
What Happens When We Retry?
Choosing Between Alternatives
Using Higher Order Code with Transactions
I/O and STM
Communication Between Threads
A Concurrent Web Link Checker
Checking a Link
Worker Threads
Finding Links
Command-Line Parsing
Pattern Guards
Practical Aspects of STM
Getting Comfortable with Giving Up Control
Using Invariants
A. Installing GHC and Haskell Libraries
B. Characters, Strings, and Escaping Rules
Index
^ 收 起
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Chunking a List
Generating a List of Candidate Digits
Life Without Arrays or Hash Tables
A Forest of Solutions
A Brief Introduction to Maps
Further Reading
Turning Digit Soup into an Answer
Solving for Check Digits in Parallel
Completing the Solution Map with the First Digit
Finding the Correct Sequence
Working with Row Data
Pulling It All Together
A Few Comments on Development Style
13. Data Structures
Association Lists
Maps
Functions Are Data, Too
Extended Example: /etc/passwd
Extended Example: Numeric Types
First Steps
Completed Code
Taking Advantage of Functions as Data
Turning Difference Lists into a Proper Library
Lists, Difference Lists, and Monoids
General-Purpose Sequences
14. Monads
Revisiting Earlier Code Examples
Maybe Chaining
Implicit State
Looking for Shared Patterns
The Monad Typeclass
And Now, a Jargon Moment
Using a New Monad: Show Your Work!
Information Hiding
Controlled Escape
Leaving a Trace
Using the Logger Monad
Mixing Pure and Monadic Code
Putting a Few Misconceptions to Rest
Building the Logger Monad
Sequential Logging, Not Sequential Evaluation
The Writer Monad
The Maybe Monad
Executing the Maybe Monad
Maybe at Work, and Good API Design
The List Monad
Understanding the List Monad
Putting the List Monad to Work
Desugaring of do Blocks
Monads as a Programmable Semicolon
Why Go Sugar-Free?
The State Monad
Almost a State Monad
Reading and Modifying the State
Will the Real State Monad Please Stand Up?
Using the State Monad: Generating Random Values
A First Attempt at Purity
Random Values in the State Monad
Running the State Monad
What About a Bit More State?
Monads and Functors
Another Way of Looking at Monads
The Monad Laws and Good Coding Style
15. Programming with Monads
Golfing Practice: Association Lists
Generalized Lifting
Looking for Alternatives
The Name mplus Does Not Imply Addition
Rules for Working with MonadPlus
Failing Safely with MonadPlus
Adventures in Hiding the Plumbing
Supplying Random Numbers
Another Round of Golf
Separating Interface from Implementation
Multiparameter Typeclasses
Functional Dependencies
Rounding Out Our Module
Programming to a Monad’s Interface
The Reader Monad
A Return to Automated Deriving
Hiding the IO Monad
Using a newtype
Designing for Unexpected Uses
Using Typeclasses
Isolation and Testing
The Writer Monad and Lists
Arbitrary I/O Revisited
16. Using Parsec
First Steps with Parsec: Simple CSV Parsing
The sepBy and endBy Combinators
Choices and Errors
Lookahead
Error Handling
Extended Example: Full CSV Parser
Parsec and MonadPlus
Parsing a URL-Encoded Query String
Supplanting Regular Expressions for Casual Parsing
Parsing Without Variables
Applicative Functors for Parsing
Applicative Parsing by Example
Parsing JSON Data
Parsing a HTTP Request
Backtracking and Its Discontents
Parsing Headers
17. Interfacing with C: The FFI
Foreign Language Bindings: The Basics
Be Careful of Side Effects
A High-Level Wrapper
Regular Expressions for Haskell: A Binding for PCRE
Simple Tasks: Using the C Preprocessor
Binding Haskell to C with hsc2hs
Adding Type Safety to PCRE
Binding to Constants
Automating the Binding
Passing String Data Between Haskell and C
Typed Pointers
Memory Management: Let the Garbage Collector Do the Work
A High-Level Interface: Marshaling Data
Marshaling ByteStrings
Allocating Local C Data: The Storable Class
Putting It All Together
Matching on Strings
Extracting Information About the Pattern
Pattern Matching with Substrings
The Real Deal: Compiling and Matching Regular Expressions
18. Monad Transformers
Motivation: Boilerplate Avoidance
A Simple Monad Transformer Example
Common Patterns in Monads and Monad Transformers
Stacking Multiple Monad Transformers
Hiding Our Work
Moving Down the Stack
When Explicit Lifting Is Necessary
Understanding Monad Transformers by Building One
Creating a Monad Transformer
More Typeclass Instances
Replacing the Parse Type with a Monad Stack
Transformer Stacking Order Is Important
Putting Monads and Monad Transformers into Perspective
Interference with Pure Code
Overdetermined Ordering
Runtime Overhead
Unwieldy Interfaces
Pulling It All Together
19. Error Handling
Error Handling with Data Types
Use of Maybe
Use of Either
Exceptions
First Steps with Exceptions
Laziness and Exception Handling
Using handle
Selective Handling of Exceptions
I/O Exceptions
Throwing Exceptions
Dynamic Exceptions
Error Handling in Monads
A Tiny Parsing Framework
20. Systems Programming in Haskell
Running External Programs
Directory and File Information
Program Termination
Dates and Times
ClockTime and CalendarTime
File Modification Times
Extended Example: Piping
Using Pipes for Redirection
Better Piping
Final Words on Pipes
21. Using Databases
Overview of HDBC
Installing HDBC and Drivers
Connecting to Databases
Transactions
Simple Queries
SqlValue
Query Parameters
Prepared Statements
Reading Results
Reading with Statements
Lazy Reading
Database Metadata
Error Handling
22. Extended Example: Web Client Programming
Basic Types
The Database
The Parser
Downloading
Main Program
23. GUI Programming with gtk2hs
Installing gtk2hs
Overview of the GTK+ Stack
User Interface Design with Glade
Glade Concepts
Event-Driven Programming
Initializing the GUI
The Add Podcast Window
Long-Running Tasks
Using Cabal
24. Concurrent and Multicore Programming
Defining Concurrency and Parallelism
Concurrent Programming with Threads
Threads Are Nondeterministic
Hiding Latency
Simple Communication Between Threads
The Main Thread and Waiting for Other Threads
Safely Modifying an MVar
Safe Resource Management: A Good Idea, and Easy Besides
Finding the Status of a Thread
Writing Tighter Code
Communicating over Channels
Useful Things to Know About
MVar and Chan Are Nonstrict
Chan Is Unbounded
Shared-State Concurrency Is Still Hard
Deadlock
Starvation
Is There Any Hope?
Using Multiple Cores with GHC
Runtime Options
Finding the Number of Available Cores from Haskell
Choosing the Right Runtime
Parallel Programming in Haskell
Normal Form and Head Normal Form
Sequential Sorting
Transforming Our Code into Parallel Code
Knowing What to Evaluate in Parallel
What Promises Does par Make?
Running Our Code and Measuring Performance
Tuning for Performance
Parallel Strategies and MapReduce
Separating Algorithm from Evaluation
Separating Algorithm from Strategy
Writing a Simple MapReduce Definition
MapReduce and Strategies
Sizing Work Appropriately
Efficiently Finding Line-Aligned Chunks
Counting Lines
Finding the Most Popular URLs
Conclusions
25. Profiling and Optimization
Profiling Haskell Programs
Collecting Runtime Statistics
Time Profiling
Space Profiling
Controlling Evaluation
Strictness and Tail Recursion
Adding Strictness
Understanding Core
Advanced Techniques: Fusion
Tuning the Generated Assembly
Conclusions
26. Advanced Library Design: Building a Bloom Filter
Introducing the Bloom Filter
Use Cases and Package Layout
Basic Design
Unboxing, Lifting, and Bottom
The ST Monad
Designing an API for Qualified Import
Creating a Mutable Bloom Filter
The Immutable API
Creating a Friendly Interface
Re-Exporting Names for Convenience
Hashing Values
Turning Two Hashes into Many
Implementing the Easy Creation Function
Creating a Cabal Package
Dealing with Different Build Setups
Compilation Options and Interfacing to C
Testing with QuickCheck
Polymorphic Testing
Writing Arbitrary Instances for ByteStrings
Are Suggested Sizes Correct?
Performance Analysis and Tuning
Profile-Driven Performance Tuning
27. Sockets and Syslog
Basic Networking
Communicating with UDP
UDP Client Example: syslog
UDP Syslog Server
Communicating with TCP
Handling Multiple TCP Streams
TCP Syslog Server
TCP Syslog Client
28. Software Transactional Memory
The Basics
Some Simple Examples
STM and Safety
Retrying a Transaction
What Happens When We Retry?
Choosing Between Alternatives
Using Higher Order Code with Transactions
I/O and STM
Communication Between Threads
A Concurrent Web Link Checker
Checking a Link
Worker Threads
Finding Links
Command-Line Parsing
Pattern Guards
Practical Aspects of STM
Getting Comfortable with Giving Up Control
Using Invariants
A. Installing GHC and Haskell Libraries
B. Characters, Strings, and Escaping Rules
Index
^ 收 起
目 录内容简介
Haskell is most likely quite different from any language youve ever used before. Compared to the usual set of concepts in a programmers mental toolbox, functional programming offers us a profoundly different way to think about software.
In Haskell, we deemphasize code that modifies data. Instead, we focus on functions that take immutable values as input and produce new values as output. Given the same inputs, these functions always return the same results. This is a core idea behind functional programming.
^ 收 起
In Haskell, we deemphasize code that modifies data. Instead, we focus on functions that take immutable values as input and produce new values as output. Given the same inputs, these functions always return the same results. This is a core idea behind functional programming.
^ 收 起
比价列表
1人想要2人拥有
公众号、微信群
缺书网
微信公众号
微信公众号
扫码进群
实时获取购书优惠
实时获取购书优惠