真实世界的Haskell

出版时间:2010-1  出版社:东南大学出版社  作者:[美] 沙利文,[美] 戈尔,[美] 斯图尔特  页数:670  
Tag标签:无  

前言

  Have We Got a Deal for You!  Haskell is a deep language; we think learning it is a hugely rewarding experience. We will focus on three elements as we explain why. The first is novelty: we invite you to think about programming from a different and valuable perspective. The second is power: well show you how to create software that is short, fast, and safe. Lastly, we offer you a lot of enjoyment: the pleasure of applying beautiful programming techniques to solve real problems.  Novelty  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.  Along with not modifying data, our Haskell functions usually dont talk to the external world; we call these functions pure. We make a strong distinction between pure code and the parts of our programs that read or write files, communicate over network connections, or make robot arms move. This makes it easier to organize, reason about, and test our programs.  We abandon some ideas that might seem fundamental, such as having a for loop built into the language. We have other, more flexible, ways to perform repetitive tasks. Even the way in which we evaluate expressions is different in Haskell. We defer every computation until its result is actually needed——Haskell is a lazy language. Laziness is not merely a matter of moving work around, it profoundly affects how we write programs.  Power  Throughout this book, we will show you how Haskells alternatives to the features of traditional languages are powerful and flexible and lead to reliable code. Haskell is positively crammed full of cutting-edge ideas about how to create great software.  Since pure code has no dealings with the outside world, and the data it works with is never modified, the kind of nasty surprise in which one piece of code invisibly corrupts data used by another is very rare. Whatever context we use a pure function in, the function will behave consistently.

内容概要

  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.

书籍目录

Preface1. Getting StartedYour Haskell EnvironmentGetting Started with ghci, the InterpreterBasic Interaction: Using ghci as a CalculatorSimple ArithmeticAn Arithmetic Quirk: Writing Negative NumbersBoolean Logic, Operators, and Value ComparisonsOperator Precedence and AssociativityUndefined Values, and Introducing VariablesDealing with Precedence and Associativity RulesCommand-Line Editing in ghciListsOperators on ListsStrings and CharactersFirst Steps with TypesA Simple Program2. Types and FunctionsWhy Care About Types?Haskell’s Type SystemStrong TypesStatic TypesType InferenceWhat to Expect from the Type SystemSome Common Basic TypesFunction ApplicationUseful Composite Data Types: Lists and TuplesFunctions over Lists and TuplesPassing an Expression to a FunctionFunction Types and PurityHaskell Source Files, and Writing Simple FunctionsJust What Is a Variable, Anyway?Conditional EvaluationUnderstanding Evaluation by ExampleLazy EvaluationA More Involved ExampleRecursionEnding the RecursionReturning from the RecursionWhat Have We Learned?Polymorphism in HaskellReasoning About Polymorphic FunctionsFurther ReadingThe Type of a Function of More Than One ArgumentWhy the Fuss over Purity?Conclusion3. Defining Types, Streamlining FunctionsDefining a New Data TypeNaming Types and ValuesType SynonymsAlgebraic Data TypesTuples, Algebraic Data Types, and When to Use EachAnalogues to Algebraic Data Types in Other LanguagesPattern MatchingConstruction and DeconstructionFurther AdventuresVariable Naming in PatternsThe Wild Card PatternExhaustive Patterns and Wild CardsRecord SyntaxParameterized TypesRecursive TypesReporting ErrorsA More Controlled ApproachIntroducing Local VariablesShadowingThe where ClauseLocal Functions, Global VariablesThe Offside Rule and Whitespace in an ExpressionA Note About Tabs Versus SpacesThe Offside Rule Is Not MandatoryThe case ExpressionCommon Beginner Mistakes with PatternsIncorrectly Matching Against a VariableIncorrectly Trying to Compare for EqualityConditional Evaluation with Guards4. Functional ProgrammingThinking in HaskellA Simple Command-Line FrameworkWarming Up: Portably Splitting Lines of TextA Line-Ending Conversion ProgramInfix FunctionsWorking with ListsBasic List ManipulationSafely and Sanely Working with Crashy FunctionsPartial and Total FunctionsMore Simple List ManipulationsWorking with SublistsSearching ListsWorking with Several Lists at OnceSpecial String-Handling FunctionsHow to Think About LoopsExplicit RecursionTransforming Every Piece of InputMapping over a ListSelecting Pieces of InputComputing One Answer over a CollectionThe Left FoldWhy Use Folds, Maps, and Filters?Folding from the RightLeft Folds, Laziness, and Space LeaksFurther ReadingAnonymous (lambda) FunctionsPartial Function Application and CurryingSectionsAs-patternsCode Reuse Through CompositionUse Your Head WiselyTips for Writing Readable CodeSpace Leaks and Strict EvaluationAvoiding Space Leaks with seqLearning to Use seq5. Writing a Library: Working with JSON DataA Whirlwind Tour of JSONRepresenting JSON Data in HaskellThe Anatomy of a Haskell ModuleCompiling Haskell SourceGenerating a Haskell Program and Importing ModulesPrinting JSON DataType Inference Is a Double-Edged SwordA More General Look at RenderingDeveloping Haskell Code Without Going NutsPretty Printing a StringArrays and Objects, and the Module HeaderWriting a Module HeaderFleshing Out the Pretty-Printing LibraryCompact RenderingTrue Pretty PrintingFollowing the Pretty PrinterCreating a PackageWriting a Package DescriptionGHC’s Package ManagerSetting Up, Building, and InstallingPractical Pointers and Further Reading6. Using TypeclassesThe Need for TypeclassesWhat Are Typeclasses?Declaring Typeclass InstancesImportant Built-in TypeclassesShowReadSerialization with read and showNumeric TypesEquality, Ordering, and ComparisonsAutomatic DerivationTypeclasses at Work: Making JSON Easier to UseMore Helpful ErrorsMaking an Instance with a Type SynonymLiving in an Open WorldWhen Do Overlapping Instances Cause Problems?Relaxing Some Restrictions on TypeclassesHow Does Show Work for Strings?How to Give a Type a New IdentityDifferences Between Data and Newtype DeclarationsSummary: The Three Ways of Naming TypesJSON Typeclasses Without Overlapping InstancesThe Dreaded Monomorphism RestrictionConclusion7. I/OClassic I/O in HaskellPure Versus I/OWhy Purity MattersWorking with Files and HandlesMore on openFileClosing HandlesSeek and TellStandard Input, Output, and ErrorDeleting and Renaming FilesTemporary FilesExtended Example: Functional I/O and Temporary FilesLazy I/OhGetContentsreadFile and writeFileA Word on Lazy OutputinteractThe IO MonadActionsSequencingThe True Nature of ReturnIs Haskell Really Imperative?Side Effects with Lazy I/OBufferingBuffering ModesFlushing The BufferReading Command-Line ArgumentsEnvironment Variables8. Efficient File Processing, Regular Expressions, and Filename MatchingEfficient File ProcessingBinary I/O and Qualified ImportsText I/OFilename MatchingRegular Expressions in HaskellThe Many Types of ResultMore About Regular ExpressionsMixing and Matching String TypesOther Things You Should KnowTranslating a glob Pattern into a Regular ExpressionAn important Aside: Writing Lazy FunctionsMaking Use of Our Pattern MatcherHandling Errors Through API DesignPutting Our Code to Work9. I/O Case Study: A Library for Searching the FilesystemThe find CommandStarting Simple: Recursively Listing a DirectoryRevisiting Anonymous and Named FunctionsWhy Provide Both mapM and forM?A Naive Finding FunctionPredicates: From Poverty to Riches, While Remaining PureSizing a File SafelyThe Acquire-Use-Release CycleA Domain-Specific Language for PredicatesAvoiding Boilerplate with LiftingGluing Predicates TogetherDefining and Using New OperatorsControlling TraversalDensity, Readability, and the Learning ProcessAnother Way of Looking at TraversalUseful Coding GuidelinesCommon Layout Styles10. Code Case Study: Parsing a Binary Data FormatGrayscale FilesParsing a Raw PGM FileGetting Rid of Boilerplate CodeImplicit StateThe Identity ParserRecord Syntax, Updates, and Pattern MatchingA More Interesting ParserObtaining and Modifying the Parse StateReporting Parse ErrorsChaining Parsers TogetherIntroducing FunctorsConstraints on Type Definitions Are BadInfix Use of fmapFlexible InstancesThinking More About FunctorsWriting a Functor Instance for ParseUsing Functors for ParsingRewriting Our PGM ParserFuture Directions11. Testing and Quality AssuranceQuickCheck: Type-Based TestingTesting for PropertiesTesting Against a ModelTesting Case Study: Specifying a Pretty PrinterGenerating Test DataTesting Document ConstructionUsing Lists as a ModelPutting It All TogetherMeasuring Test Coverage with HPC12. Barcode RecognitionA Little Bit About BarcodesEAN-13 EncodingIntroducing ArraysArrays and LazinessFolding over ArraysModifying Array ElementsEncoding an EAN-13 BarcodeConstraints on Our DecoderDivide and ConquerTurning a Color Image into Something TractableParsing a Color ImageGrayscale ConversionGrayscale to Binary and Type SafetyWhat Have We Done to Our Image?Finding Matching DigitsRun Length EncodingScaling Run Lengths, and Finding Approximate MatchesList ComprehensionsRemembering a Match’s ParityChunking a ListGenerating a List of Candidate DigitsLife Without Arrays or Hash TablesA Forest of SolutionsA Brief Introduction to MapsFurther ReadingTurning Digit Soup into an AnswerSolving for Check Digits in ParallelCompleting the Solution Map with the First DigitFinding the Correct SequenceWorking with Row DataPulling It All TogetherA Few Comments on Development Style13. Data StructuresAssociation ListsMapsFunctions Are Data, TooExtended Example: /etc/passwdExtended Example: Numeric TypesFirst StepsCompleted CodeTaking Advantage of Functions as DataTurning Difference Lists into a Proper LibraryLists, Difference Lists, and MonoidsGeneral-Purpose Sequences14. MonadsRevisiting Earlier Code ExamplesMaybe ChainingImplicit StateLooking for Shared PatternsThe Monad TypeclassAnd Now, a Jargon MomentUsing a New Monad: Show Your Work!Information HidingControlled EscapeLeaving a TraceUsing the Logger MonadMixing Pure and Monadic CodePutting a Few Misconceptions to RestBuilding the Logger MonadSequential Logging, Not Sequential EvaluationThe Writer MonadThe Maybe MonadExecuting the Maybe MonadMaybe at Work, and Good API DesignThe List MonadUnderstanding the List MonadPutting the List Monad to WorkDesugaring of do BlocksMonads as a Programmable SemicolonWhy Go Sugar-Free?The State MonadAlmost a State MonadReading and Modifying the StateWill the Real State Monad Please Stand Up?Using the State Monad: Generating Random ValuesA First Attempt at PurityRandom Values in the State MonadRunning the State MonadWhat About a Bit More State?Monads and FunctorsAnother Way of Looking at MonadsThe Monad Laws and Good Coding Style15. Programming with MonadsGolfing Practice: Association ListsGeneralized LiftingLooking for AlternativesThe Name mplus Does Not Imply AdditionRules for Working with MonadPlusFailing Safely with MonadPlusAdventures in Hiding the PlumbingSupplying Random NumbersAnother Round of GolfSeparating Interface from ImplementationMultiparameter TypeclassesFunctional DependenciesRounding Out Our ModuleProgramming to a Monad’s InterfaceThe Reader MonadA Return to Automated DerivingHiding the IO MonadUsing a newtypeDesigning for Unexpected UsesUsing TypeclassesIsolation and TestingThe Writer Monad and ListsArbitrary I/O Revisited16. Using ParsecFirst Steps with Parsec: Simple CSV ParsingThe sepBy and endBy CombinatorsChoices and ErrorsLookaheadError HandlingExtended Example: Full CSV ParserParsec and MonadPlusParsing a URL-Encoded Query StringSupplanting Regular Expressions for Casual ParsingParsing Without VariablesApplicative Functors for ParsingApplicative Parsing by ExampleParsing JSON DataParsing a HTTP RequestBacktracking and Its DiscontentsParsing Headers17. Interfacing with C: The FFIForeign Language Bindings: The BasicsBe Careful of Side EffectsA High-Level WrapperRegular Expressions for Haskell: A Binding for PCRESimple Tasks: Using the C PreprocessorBinding Haskell to C with hsc2hsAdding Type Safety to PCREBinding to ConstantsAutomating the BindingPassing String Data Between Haskell and CTyped PointersMemory Management: Let the Garbage Collector Do the WorkA High-Level Interface: Marshaling DataMarshaling ByteStringsAllocating Local C Data: The Storable ClassPutting It All TogetherMatching on StringsExtracting Information About the PatternPattern Matching with SubstringsThe Real Deal: Compiling and Matching Regular Expressions18. Monad TransformersMotivation: Boilerplate AvoidanceA Simple Monad Transformer ExampleCommon Patterns in Monads and Monad TransformersStacking Multiple Monad TransformersHiding Our WorkMoving Down the StackWhen Explicit Lifting Is NecessaryUnderstanding Monad Transformers by Building OneCreating a Monad TransformerMore Typeclass InstancesReplacing the Parse Type with a Monad StackTransformer Stacking Order Is ImportantPutting Monads and Monad Transformers into PerspectiveInterference with Pure CodeOverdetermined OrderingRuntime OverheadUnwieldy InterfacesPulling It All Together19. Error HandlingError Handling with Data TypesUse of MaybeUse of EitherExceptionsFirst Steps with ExceptionsLaziness and Exception HandlingUsing handleSelective Handling of ExceptionsI/O ExceptionsThrowing ExceptionsDynamic ExceptionsError Handling in MonadsA Tiny Parsing Framework20. Systems Programming in HaskellRunning External ProgramsDirectory and File InformationProgram TerminationDates and TimesClockTime and CalendarTimeFile Modification TimesExtended Example: PipingUsing Pipes for RedirectionBetter PipingFinal Words on Pipes21. Using DatabasesOverview of HDBCInstalling HDBC and DriversConnecting to DatabasesTransactionsSimple QueriesSqlValueQuery ParametersPrepared StatementsReading ResultsReading with StatementsLazy ReadingDatabase MetadataError Handling22. Extended Example: Web Client ProgrammingBasic TypesThe DatabaseThe ParserDownloadingMain Program23. GUI Programming with gtk2hsInstalling gtk2hsOverview of the GTK+ StackUser Interface Design with GladeGlade ConceptsEvent-Driven ProgrammingInitializing the GUIThe Add Podcast WindowLong-Running TasksUsing Cabal24. Concurrent and Multicore ProgrammingDefining Concurrency and ParallelismConcurrent Programming with ThreadsThreads Are NondeterministicHiding LatencySimple Communication Between ThreadsThe Main Thread and Waiting for Other ThreadsSafely Modifying an MVarSafe Resource Management: A Good Idea, and Easy BesidesFinding the Status of a ThreadWriting Tighter CodeCommunicating over ChannelsUseful Things to Know AboutMVar and Chan Are NonstrictChan Is UnboundedShared-State Concurrency Is Still HardDeadlockStarvationIs There Any Hope?Using Multiple Cores with GHCRuntime OptionsFinding the Number of Available Cores from HaskellChoosing the Right RuntimeParallel Programming in HaskellNormal Form and Head Normal FormSequential SortingTransforming Our Code into Parallel CodeKnowing What to Evaluate in ParallelWhat Promises Does par Make?Running Our Code and Measuring PerformanceTuning for PerformanceParallel Strategies and MapReduceSeparating Algorithm from EvaluationSeparating Algorithm from StrategyWriting a Simple MapReduce DefinitionMapReduce and StrategiesSizing Work AppropriatelyEfficiently Finding Line-Aligned ChunksCounting LinesFinding the Most Popular URLsConclusions25. Profiling and OptimizationProfiling Haskell ProgramsCollecting Runtime StatisticsTime ProfilingSpace ProfilingControlling EvaluationStrictness and Tail RecursionAdding StrictnessUnderstanding CoreAdvanced Techniques: FusionTuning the Generated AssemblyConclusions26. Advanced Library Design: Building a Bloom FilterIntroducing the Bloom FilterUse Cases and Package LayoutBasic DesignUnboxing, Lifting, and BottomThe ST MonadDesigning an API for Qualified ImportCreating a Mutable Bloom FilterThe Immutable APICreating a Friendly InterfaceRe-Exporting Names for ConvenienceHashing ValuesTurning Two Hashes into ManyImplementing the Easy Creation FunctionCreating a Cabal PackageDealing with Different Build SetupsCompilation Options and Interfacing to CTesting with QuickCheckPolymorphic TestingWriting Arbitrary Instances for ByteStringsAre Suggested Sizes Correct?Performance Analysis and TuningProfile-Driven Performance Tuning27. Sockets and SyslogBasic NetworkingCommunicating with UDPUDP Client Example: syslogUDP Syslog ServerCommunicating with TCPHandling Multiple TCP StreamsTCP Syslog ServerTCP Syslog Client28. Software Transactional MemoryThe BasicsSome Simple ExamplesSTM and SafetyRetrying a TransactionWhat Happens When We Retry?Choosing Between AlternativesUsing Higher Order Code with TransactionsI/O and STMCommunication Between ThreadsA Concurrent Web Link CheckerChecking a LinkWorker ThreadsFinding LinksCommand-Line ParsingPattern GuardsPractical Aspects of STMGetting Comfortable with Giving Up ControlUsing InvariantsA. Installing GHC and Haskell LibrariesB. Characters, Strings, and Escaping RulesIndex

章节摘录

  In this section, weve discussed how Haskell, unlike most languages, draws a cleardistinction between pure code and I/O actions. In languages such as C or Java, thereis no such thing as a function that is guaranteed by the compiler to always return thesame result for the same arguments or a function that is guaranteed to never have sideeffects. The only way to know if a given function has side effects is to read its docu-mentation and hope that its accurate.Many bugs in programs are caused by unanticipated side effects. Still more are causedby misunderstanding circumstances in which functions may return different results forthe same input. As multithreading and other forms of parallelism grow increasinglycommon, it becomes more difficult to manage global side effects.Haskells method of isolating side effects into I/O actions provides a clear boundary.You can always know which parts of the system may alter state and which wont. Youcan always he sure that the pure parts of your program arent having unanticipatedresults. This helps you to think about the program. It also helps the compiler to thinkabout it. Recent versions of ghc, for instance, can provide a level of automatic paral-lelism for the pure parts of your code——something of a holy grail for computing.For more discussion on this topic, refer to "Side Effects with Lazy I/O" on page 188.

媒体关注与评论

  “现代软件的最大问题在于性能、模块化、可靠性和并发性。在《真实世界的Haskell》中,作者很好地讲授了如何使用HaskeII这一超前于当今主流的语言,来逐一化解这些问题。”  ——Trim Sweeney,Epic Games创始人,同时也是Unreal 游戏引擎设计者  “这是第一本涵盖了现实世界程序员所需一切技术的书籍。当读罢此书,你将能够用当前所钟爱的语言写出更优秀的代码。”  ——Simon Peyton Jones.Microsoft Research Haskell语言架构师,GlasgowHaskell 编译器设计者

编辑推荐

  《真实世界的Haskell(影印版)》是一本上手快且易于使用的指导书,它向你介绍这门日趋流行的编程语言。你将学习如何将Haskell应用于不同实践当中,从简短的脚本到要求苛刻的大型应用。《真实世界的Haskell(影印版)》向你讲解了函数式编程的基础,帮助你加深对如何在现实世界中应用Haskell的理解,例如输入/输出性能、数据处理、并发等等。  《真实世界的Haskell》能帮助你:  ·理解过程式与函数式编程之间的差异  ·学习Haskell的特性,以及如何使用它来开发有用的程序  ·与文件系统、数据库和网络服务交互  ·编写可以进行自动测试、代码覆盖和错误处理的代码  ·通过并发和并行编程发挥多核系统的威力  在《真实世界的Haskell(影印版)》中你将发现大量的实用习题和真实的Haskell程序示例,你可以修改、编译及运行它们。无论是否曾经使用过函数式语言,如果想要了解Haskell为何成为众多组织所选用的实用语言,《真实世界的Haskell》是你的首选。

图书封面

图书标签Tags

评论、评分、阅读与下载


    真实世界的Haskell PDF格式下载


用户评论 (总计2条)

 
 

  •   学习函数式编程首选
  •   当当送来的书太旧了,像二手的一样
 

250万本中文图书简介、评论、评分,PDF格式免费下载。 第一图书网 手机版

京ICP备13047387号-7