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.
作者簡介
暫缺《真實世界的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 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