真实世界的Haskell(影印版)

真实世界的Haskell(影印版)
作 者: 沙利文 戈尔 斯图尔特
出版社: 东南大学出版社
丛编项:
版权说明: 本书为公共版权或经版权方授权,请支持正版图书
标 签: 软件工程/开发项目管理
ISBN 出版时间 包装 开本 页数 字数
未知 暂无 暂无 未知 0 暂无

作者简介

暂缺《真实世界的Haskell(影印版)》作者简介

内容简介

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.

图书目录

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