真实世界的Haskell(影印版)
真实世界的Haskell(影印版)
Bryan O'Sullivan, John Goerzen, Don Stewart
出版时间:2009年12月
页数:670
《真实世界的Haskell》是一本上手快且易于使用的指导书,它向你介绍这门日趋流行的编程语言。你将学习如何将Haskell应用于不同实践当中,从简短的脚本到要求苛刻的大型应用。本书向你讲解了函数式编程的基础,帮助你加深对如何在现实世界中应用Haskell的理解,例如输入/输出性能、数据处理、并发等等。
《真实世界的Haskell》能帮助你:
* 理解过程式与函数式编程之间的差异
* 学习Haskell的特性,以及如何使用它来开发有用的程序
* 与文件系统、数据库和网络服务交互
* 编写可以进行自动测试、代码覆盖和错误处理的代码
* 通过并发和并行编程发挥多核系统的威力
在本书中你将发现大量的实用习题和真实的Haskell程序示例,你可以修改、编译及运行它们。无论是否曾经使用过函数式语言,如果想要了解Haskell为何成为众多组织所选用的实用语言,《真实世界的Haskell》是你的首选。
“现代软件的最大问题在于性能、模块化、可靠性和并发性。在《真实世界的Haskell》中,作者很好地讲授了如何使用Haskell这一超前于当今主流的语言,来逐一化解这些问题。”
——Tim Sweeney,Epic Games创始人,同时也是Unreal游戏引擎设计者
“这是第一本涵盖了现实世界程序员所需一切技术的书籍。当读罢此书,你将能够用当前所钟爱的语言写出更优秀的代码。”
──Simon Peyton Jones,Microsoft Research
Haskell语言架构师,Glasgow Haskell编译器设计者
  1. Preface
  2. 1. Getting Started
  3. Your Haskell Environment
  4. Getting Started with ghci, the Interpreter
  5. Basic Interaction: Using ghci as a Calculator
  6. Simple Arithmetic
  7. An Arithmetic Quirk: Writing Negative Numbers
  8. Boolean Logic, Operators, and Value Comparisons
  9. Operator Precedence and Associativity
  10. Undefined Values, and Introducing Variables
  11. Dealing with Precedence and Associativity Rules
  12. Command-Line Editing in ghci
  13. Lists
  14. Operators on Lists
  15. Strings and Characters
  16. First Steps with Types
  17. A Simple Program
  18. 2. Types and Functions
  19. Why Care About Types?
  20. Haskell’s Type System
  21. Strong Types
  22. Static Types
  23. Type Inference
  24. What to Expect from the Type System
  25. Some Common Basic Types
  26. Function Application
  27. Useful Composite Data Types: Lists and Tuples
  28. Functions over Lists and Tuples
  29. Passing an Expression to a Function
  30. Function Types and Purity
  31. Haskell Source Files, and Writing Simple Functions
  32. Just What Is a Variable, Anyway?
  33. Conditional Evaluation
  34. Understanding Evaluation by Example
  35. Lazy Evaluation
  36. A More Involved Example
  37. Recursion
  38. Ending the Recursion
  39. Returning from the Recursion
  40. What Have We Learned?
  41. Polymorphism in Haskell
  42. Reasoning About Polymorphic Functions
  43. Further Reading
  44. The Type of a Function of More Than One Argument
  45. Why the Fuss over Purity?
  46. Conclusion
  47. 3. Defining Types, Streamlining Functions
  48. Defining a New Data Type
  49. Naming Types and Values
  50. Type Synonyms
  51. Algebraic Data Types
  52. Tuples, Algebraic Data Types, and When to Use Each
  53. Analogues to Algebraic Data Types in Other Languages
  54. Pattern Matching
  55. Construction and Deconstruction
  56. Further Adventures
  57. Variable Naming in Patterns
  58. The Wild Card Pattern
  59. Exhaustive Patterns and Wild Cards
  60. Record Syntax
  61. Parameterized Types
  62. Recursive Types
  63. Reporting Errors
  64. A More Controlled Approach
  65. Introducing Local Variables
  66. Shadowing
  67. The where Clause
  68. Local Functions, Global Variables
  69. The Offside Rule and Whitespace in an Expression
  70. A Note About Tabs Versus Spaces
  71. The Offside Rule Is Not Mandatory
  72. The case Expression
  73. Common Beginner Mistakes with Patterns
  74. Incorrectly Matching Against a Variable
  75. Incorrectly Trying to Compare for Equality
  76. Conditional Evaluation with Guards
  77. 4. Functional Programming
  78. Thinking in Haskell
  79. A Simple Command-Line Framework
  80. Warming Up: Portably Splitting Lines of Text
  81. A Line-Ending Conversion Program
  82. Infix Functions
  83. Working with Lists
  84. Basic List Manipulation
  85. Safely and Sanely Working with Crashy Functions
  86. Partial and Total Functions
  87. More Simple List Manipulations
  88. Working with Sublists
  89. Searching Lists
  90. Working with Several Lists at Once
  91. Special String-Handling Functions
  92. How to Think About Loops
  93. Explicit Recursion
  94. Transforming Every Piece of Input
  95. Mapping over a List
  96. Selecting Pieces of Input
  97. Computing One Answer over a Collection
  98. The Left Fold
  99. Why Use Folds, Maps, and Filters?
  100. Folding from the Right
  101. Left Folds, Laziness, and Space Leaks
  102. Further Reading
  103. Anonymous (lambda) Functions
  104. Partial Function Application and Currying
  105. Sections
  106. As-patterns
  107. Code Reuse Through Composition
  108. Use Your Head Wisely
  109. Tips for Writing Readable Code
  110. Space Leaks and Strict Evaluation
  111. Avoiding Space Leaks with seq
  112. Learning to Use seq
  113. 5. Writing a Library: Working with JSON Data
  114. A Whirlwind Tour of JSON
  115. Representing JSON Data in Haskell
  116. The Anatomy of a Haskell Module
  117. Compiling Haskell Source
  118. Generating a Haskell Program and Importing Modules
  119. Printing JSON Data
  120. Type Inference Is a Double-Edged Sword
  121. A More General Look at Rendering
  122. Developing Haskell Code Without Going Nuts
  123. Pretty Printing a String
  124. Arrays and Objects, and the Module Header
  125. Writing a Module Header
  126. Fleshing Out the Pretty-Printing Library
  127. Compact Rendering
  128. True Pretty Printing
  129. Following the Pretty Printer
  130. Creating a Package
  131. Writing a Package Description
  132. GHC’s Package Manager
  133. Setting Up, Building, and Installing
  134. Practical Pointers and Further Reading
  135. 6. Using Typeclasses
  136. The Need for Typeclasses
  137. What Are Typeclasses?
  138. Declaring Typeclass Instances
  139. Important Built-in Typeclasses
  140. Show
  141. Read
  142. Serialization with read and show
  143. Numeric Types
  144. Equality, Ordering, and Comparisons
  145. Automatic Derivation
  146. Typeclasses at Work: Making JSON Easier to Use
  147. More Helpful Errors
  148. Making an Instance with a Type Synonym
  149. Living in an Open World
  150. When Do Overlapping Instances Cause Problems?
  151. Relaxing Some Restrictions on Typeclasses
  152. How Does Show Work for Strings?
  153. How to Give a Type a New Identity
  154. Differences Between Data and Newtype Declarations
  155. Summary: The Three Ways of Naming Types
  156. JSON Typeclasses Without Overlapping Instances
  157. The Dreaded Monomorphism Restriction
  158. Conclusion
  159. 7. I/O
  160. Classic I/O in Haskell
  161. Pure Versus I/O
  162. Why Purity Matters
  163. Working with Files and Handles
  164. More on openFile
  165. Closing Handles
  166. Seek and Tell
  167. Standard Input, Output, and Error
  168. Deleting and Renaming Files
  169. Temporary Files
  170. Extended Example: Functional I/O and Temporary Files
  171. Lazy I/O
  172. hGetContents
  173. readFile and writeFile
  174. A Word on Lazy Output
  175. interact
  176. The IO Monad
  177. Actions
  178. Sequencing
  179. The True Nature of Return
  180. Is Haskell Really Imperative?
  181. Side Effects with Lazy I/O
  182. Buffering
  183. Buffering Modes
  184. Flushing The Buffer
  185. Reading Command-Line Arguments
  186. Environment Variables
  187. 8. Efficient File Processing, Regular Expressions, and Filename Matching
  188. Efficient File Processing
  189. Binary I/O and Qualified Imports
  190. Text I/O
  191. Filename Matching
  192. Regular Expressions in Haskell
  193. The Many Types of Result
  194. More About Regular Expressions
  195. Mixing and Matching String Types
  196. Other Things You Should Know
  197. Translating a glob Pattern into a Regular Expression
  198. An important Aside: Writing Lazy Functions
  199. Making Use of Our Pattern Matcher
  200. Handling Errors Through API Design
  201. Putting Our Code to Work
  202. 9. I/O Case Study: A Library for Searching the Filesystem
  203. The find Command
  204. Starting Simple: Recursively Listing a Directory
  205. Revisiting Anonymous and Named Functions
  206. Why Provide Both mapM and forM?
  207. A Naive Finding Function
  208. Predicates: From Poverty to Riches, While Remaining Pure
  209. Sizing a File Safely
  210. The Acquire-Use-Release Cycle
  211. A Domain-Specific Language for Predicates
  212. Avoiding Boilerplate with Lifting
  213. Gluing Predicates Together
  214. Defining and Using New Operators
  215. Controlling Traversal
  216. Density, Readability, and the Learning Process
  217. Another Way of Looking at Traversal
  218. Useful Coding Guidelines
  219. Common Layout Styles
  220. 10. Code Case Study: Parsing a Binary Data Format
  221. Grayscale Files
  222. Parsing a Raw PGM File
  223. Getting Rid of Boilerplate Code
  224. Implicit State
  225. The Identity Parser
  226. Record Syntax, Updates, and Pattern Matching
  227. A More Interesting Parser
  228. Obtaining and Modifying the Parse State
  229. Reporting Parse Errors
  230. Chaining Parsers Together
  231. Introducing Functors
  232. Constraints on Type Definitions Are Bad
  233. Infix Use of fmap
  234. Flexible Instances
  235. Thinking More About Functors
  236. Writing a Functor Instance for Parse
  237. Using Functors for Parsing
  238. Rewriting Our PGM Parser
  239. Future Directions
  240. 11. Testing and Quality Assurance
  241. QuickCheck: Type-Based Testing
  242. Testing for Properties
  243. Testing Against a Model
  244. Testing Case Study: Specifying a Pretty Printer
  245. Generating Test Data
  246. Testing Document Construction
  247. Using Lists as a Model
  248. Putting It All Together
  249. Measuring Test Coverage with HPC
  250. 12. Barcode Recognition
  251. A Little Bit About Barcodes
  252. EAN-13 Encoding
  253. Introducing Arrays
  254. Arrays and Laziness
  255. Folding over Arrays
  256. Modifying Array Elements
  257. Encoding an EAN-13 Barcode
  258. Constraints on Our Decoder
  259. Divide and Conquer
  260. Turning a Color Image into Something Tractable
  261. Parsing a Color Image
  262. Grayscale Conversion
  263. Grayscale to Binary and Type Safety
  264. What Have We Done to Our Image?
  265. Finding Matching Digits
  266. Run Length Encoding
  267. Scaling Run Lengths, and Finding Approximate Matches
  268. List Comprehensions
  269. Remembering a Match’s Parity
  270. Chunking a List
  271. Generating a List of Candidate Digits
  272. Life Without Arrays or Hash Tables
  273. A Forest of Solutions
  274. A Brief Introduction to Maps
  275. Further Reading
  276. Turning Digit Soup into an Answer
  277. Solving for Check Digits in Parallel
  278. Completing the Solution Map with the First Digit
  279. Finding the Correct Sequence
  280. Working with Row Data
  281. Pulling It All Together
  282. A Few Comments on Development Style
  283. 13. Data Structures
  284. Association Lists
  285. Maps
  286. Functions Are Data, Too
  287. Extended Example: /etc/passwd
  288. Extended Example: Numeric Types
  289. First Steps
  290. Completed Code
  291. Taking Advantage of Functions as Data
  292. Turning Difference Lists into a Proper Library
  293. Lists, Difference Lists, and Monoids
  294. General-Purpose Sequences
  295. 14. Monads
  296. Revisiting Earlier Code Examples
  297. Maybe Chaining
  298. Implicit State
  299. Looking for Shared Patterns
  300. The Monad Typeclass
  301. And Now, a Jargon Moment
  302. Using a New Monad: Show Your Work!
  303. Information Hiding
  304. Controlled Escape
  305. Leaving a Trace
  306. Using the Logger Monad
  307. Mixing Pure and Monadic Code
  308. Putting a Few Misconceptions to Rest
  309. Building the Logger Monad
  310. Sequential Logging, Not Sequential Evaluation
  311. The Writer Monad
  312. The Maybe Monad
  313. Executing the Maybe Monad
  314. Maybe at Work, and Good API Design
  315. The List Monad
  316. Understanding the List Monad
  317. Putting the List Monad to Work
  318. Desugaring of do Blocks
  319. Monads as a Programmable Semicolon
  320. Why Go Sugar-Free?
  321. The State Monad
  322. Almost a State Monad
  323. Reading and Modifying the State
  324. Will the Real State Monad Please Stand Up?
  325. Using the State Monad: Generating Random Values
  326. A First Attempt at Purity
  327. Random Values in the State Monad
  328. Running the State Monad
  329. What About a Bit More State?
  330. Monads and Functors
  331. Another Way of Looking at Monads
  332. The Monad Laws and Good Coding Style
  333. 15. Programming with Monads
  334. Golfing Practice: Association Lists
  335. Generalized Lifting
  336. Looking for Alternatives
  337. The Name mplus Does Not Imply Addition
  338. Rules for Working with MonadPlus
  339. Failing Safely with MonadPlus
  340. Adventures in Hiding the Plumbing
  341. Supplying Random Numbers
  342. Another Round of Golf
  343. Separating Interface from Implementation
  344. Multiparameter Typeclasses
  345. Functional Dependencies
  346. Rounding Out Our Module
  347. Programming to a Monad’s Interface
  348. The Reader Monad
  349. A Return to Automated Deriving
  350. Hiding the IO Monad
  351. Using a newtype
  352. Designing for Unexpected Uses
  353. Using Typeclasses
  354. Isolation and Testing
  355. The Writer Monad and Lists
  356. Arbitrary I/O Revisited
  357. 16. Using Parsec
  358. First Steps with Parsec: Simple CSV Parsing
  359. The sepBy and endBy Combinators
  360. Choices and Errors
  361. Lookahead
  362. Error Handling
  363. Extended Example: Full CSV Parser
  364. Parsec and MonadPlus
  365. Parsing a URL-Encoded Query String
  366. Supplanting Regular Expressions for Casual Parsing
  367. Parsing Without Variables
  368. Applicative Functors for Parsing
  369. Applicative Parsing by Example
  370. Parsing JSON Data
  371. Parsing a HTTP Request
  372. Backtracking and Its Discontents
  373. Parsing Headers
  374. 17. Interfacing with C: The FFI
  375. Foreign Language Bindings: The Basics
  376. Be Careful of Side Effects
  377. A High-Level Wrapper
  378. Regular Expressions for Haskell: A Binding for PCRE
  379. Simple Tasks: Using the C Preprocessor
  380. Binding Haskell to C with hsc2hs
  381. Adding Type Safety to PCRE
  382. Binding to Constants
  383. Automating the Binding
  384. Passing String Data Between Haskell and C
  385. Typed Pointers
  386. Memory Management: Let the Garbage Collector Do the Work
  387. A High-Level Interface: Marshaling Data
  388. Marshaling ByteStrings
  389. Allocating Local C Data: The Storable Class
  390. Putting It All Together
  391. Matching on Strings
  392. Extracting Information About the Pattern
  393. Pattern Matching with Substrings
  394. The Real Deal: Compiling and Matching Regular Expressions
  395. 18. Monad Transformers
  396. Motivation: Boilerplate Avoidance
  397. A Simple Monad Transformer Example
  398. Common Patterns in Monads and Monad Transformers
  399. Stacking Multiple Monad Transformers
  400. Hiding Our Work
  401. Moving Down the Stack
  402. When Explicit Lifting Is Necessary
  403. Understanding Monad Transformers by Building One
  404. Creating a Monad Transformer
  405. More Typeclass Instances
  406. Replacing the Parse Type with a Monad Stack
  407. Transformer Stacking Order Is Important
  408. Putting Monads and Monad Transformers into Perspective
  409. Interference with Pure Code
  410. Overdetermined Ordering
  411. Runtime Overhead
  412. Unwieldy Interfaces
  413. Pulling It All Together
  414. 19. Error Handling
  415. Error Handling with Data Types
  416. Use of Maybe
  417. Use of Either
  418. Exceptions
  419. First Steps with Exceptions
  420. Laziness and Exception Handling
  421. Using handle
  422. Selective Handling of Exceptions
  423. I/O Exceptions
  424. Throwing Exceptions
  425. Dynamic Exceptions
  426. Error Handling in Monads
  427. A Tiny Parsing Framework
  428. 20. Systems Programming in Haskell
  429. Running External Programs
  430. Directory and File Information
  431. Program Termination
  432. Dates and Times
  433. ClockTime and CalendarTime
  434. File Modification Times
  435. Extended Example: Piping
  436. Using Pipes for Redirection
  437. Better Piping
  438. Final Words on Pipes
  439. 21. Using Databases
  440. Overview of HDBC
  441. Installing HDBC and Drivers
  442. Connecting to Databases
  443. Transactions
  444. Simple Queries
  445. SqlValue
  446. Query Parameters
  447. Prepared Statements
  448. Reading Results
  449. Reading with Statements
  450. Lazy Reading
  451. Database Metadata
  452. Error Handling
  453. 22. Extended Example: Web Client Programming
  454. Basic Types
  455. The Database
  456. The Parser
  457. Downloading
  458. Main Program
  459. 23. GUI Programming with gtk2hs
  460. Installing gtk2hs
  461. Overview of the GTK+ Stack
  462. User Interface Design with Glade
  463. Glade Concepts
  464. Event-Driven Programming
  465. Initializing the GUI
  466. The Add Podcast Window
  467. Long-Running Tasks
  468. Using Cabal
  469. 24. Concurrent and Multicore Programming
  470. Defining Concurrency and Parallelism
  471. Concurrent Programming with Threads
  472. Threads Are Nondeterministic
  473. Hiding Latency
  474. Simple Communication Between Threads
  475. The Main Thread and Waiting for Other Threads
  476. Safely Modifying an MVar
  477. Safe Resource Management: A Good Idea, and Easy Besides
  478. Finding the Status of a Thread
  479. Writing Tighter Code
  480. Communicating over Channels
  481. Useful Things to Know About
  482. MVar and Chan Are Nonstrict
  483. Chan Is Unbounded
  484. Shared-State Concurrency Is Still Hard
  485. Deadlock
  486. Starvation
  487. Is There Any Hope?
  488. Using Multiple Cores with GHC
  489. Runtime Options
  490. Finding the Number of Available Cores from Haskell
  491. Choosing the Right Runtime
  492. Parallel Programming in Haskell
  493. Normal Form and Head Normal Form
  494. Sequential Sorting
  495. Transforming Our Code into Parallel Code
  496. Knowing What to Evaluate in Parallel
  497. What Promises Does par Make?
  498. Running Our Code and Measuring Performance
  499. Tuning for Performance
  500. Parallel Strategies and MapReduce
  501. Separating Algorithm from Evaluation
  502. Separating Algorithm from Strategy
  503. Writing a Simple MapReduce Definition
  504. MapReduce and Strategies
  505. Sizing Work Appropriately
  506. Efficiently Finding Line-Aligned Chunks
  507. Counting Lines
  508. Finding the Most Popular URLs
  509. Conclusions
  510. 25. Profiling and Optimization
  511. Profiling Haskell Programs
  512. Collecting Runtime Statistics
  513. Time Profiling
  514. Space Profiling
  515. Controlling Evaluation
  516. Strictness and Tail Recursion
  517. Adding Strictness
  518. Understanding Core
  519. Advanced Techniques: Fusion
  520. Tuning the Generated Assembly
  521. Conclusions
  522. 26. Advanced Library Design: Building a Bloom Filter
  523. Introducing the Bloom Filter
  524. Use Cases and Package Layout
  525. Basic Design
  526. Unboxing, Lifting, and Bottom
  527. The ST Monad
  528. Designing an API for Qualified Import
  529. Creating a Mutable Bloom Filter
  530. The Immutable API
  531. Creating a Friendly Interface
  532. Re-Exporting Names for Convenience
  533. Hashing Values
  534. Turning Two Hashes into Many
  535. Implementing the Easy Creation Function
  536. Creating a Cabal Package
  537. Dealing with Different Build Setups
  538. Compilation Options and Interfacing to C
  539. Testing with QuickCheck
  540. Polymorphic Testing
  541. Writing Arbitrary Instances for ByteStrings
  542. Are Suggested Sizes Correct?
  543. Performance Analysis and Tuning
  544. Profile-Driven Performance Tuning
  545. 27. Sockets and Syslog
  546. Basic Networking
  547. Communicating with UDP
  548. UDP Client Example: syslog
  549. UDP Syslog Server
  550. Communicating with TCP
  551. Handling Multiple TCP Streams
  552. TCP Syslog Server
  553. TCP Syslog Client
  554. 28. Software Transactional Memory
  555. The Basics
  556. Some Simple Examples
  557. STM and Safety
  558. Retrying a Transaction
  559. What Happens When We Retry?
  560. Choosing Between Alternatives
  561. Using Higher Order Code with Transactions
  562. I/O and STM
  563. Communication Between Threads
  564. A Concurrent Web Link Checker
  565. Checking a Link
  566. Worker Threads
  567. Finding Links
  568. Command-Line Parsing
  569. Pattern Guards
  570. Practical Aspects of STM
  571. Getting Comfortable with Giving Up Control
  572. Using Invariants
  573. A. Installing GHC and Haskell Libraries
  574. B. Characters, Strings, and Escaping Rules
  575. Index
书名:真实世界的Haskell(影印版)
作者:Bryan O'Sullivan, John Goerzen, Don Stewart
国内出版社:东南大学出版社
出版时间:2009年12月
页数:670
书号:978-7-5641-1925-6
原版书出版商:O'Reilly Media
Bryan O'Sullivan
 
John Goerzen
 
John Goerzen is an American hacker and author. He has written a number of realworld
Haskell libraries and applications, including the HDBC database interface, the
ConfigFile configuration file interface, a podcast downloader, and various other libraries
relating to networks, parsing, logging, and POSIX code. John has been a developer
for the Debian GNU/Linux operating system project for over 10 years and maintains
numerous Haskell libraries and code for Debian. He also served as president of Software
in the Public Interest, Inc., the legal parent organization of Debian. John lives in rural
Kansas with his wife and son, where he enjoys photography and geocaching.
 
 
Don Stewart
 
Don Stewart is an Australian hacker based in Portland, Oregon. Don has been involved
in a diverse range of Haskell projects, including practical libraries, such as Data.Byte-
String and Data.Binary, as well as applying the Haskell philosophy to real-world applications,
including compilers, linkers, text editors, network servers, and systems
software. His recent work has focused on optimizing Haskell for high-performance
scenarios, using techniques from term rewriting.
 
 
The animal on the cover of Real World Haskell is a rhinoceros beetle, a species of scarab
beetle. Relative to their size, rhinoceros beetles are among the strongest animals on the
planet. They can lift up to 850 times their own weight. The average rhino beetle found
in the U.S. is about an inch long, but they can grow as long as seven inches.
Rhino beetles have horns on their heads, resembling that of the rhinoceros, hence the
name. The size of their horns is related to how much nutrition they had in larva. In
some species, the horns are longer than the bodies, and they can grow as many as four
or five horns. They use the horns for digging, as well as for fighting for territory and
mates.
Rhino beetles thrive on sap and rotting fruit, specifically bananas, apples, and oranges.
Their larvae, which takes between 3–5 years to mature, eat decaying wood, compost,
and dead leaves—a kind of recycling for the environment.