Functional Programming in C#, Second Edition
معرفی کتاب «Functional Programming in C#, Second Edition» نوشتهٔ Enrico Buonanno; Safari, an O'Reilly Media Company، منتشرشده توسط نشر Manning Publications Co. LLC در سال 2021. این کتاب در فرمت epub، زبان انگلیسی ارائه شده است. «Functional Programming in C#, Second Edition» در دستهٔ بدون دستهبندی قرار دارد.
Real world examples and practical techniques for functional programming in C# without the jargon and theory. In Functional Programming in C#, Second Edition you will learn how to: \* Use higher-order functions to reduce duplication and do more with less code \* Use pure functions to write code that is easy to test and optimize \* Write pleasant APIs that accurately describe your program's behavior \* Use dedicated types to handle nullability, system errors, and validation rules predictably and elegantly \* Write composable code without the overhead of an IoC container Functional Programming in C# has helped thousands of developers apply functional thinking to C# code. Its practical examples and spot-on treatment of FP concepts makes it the perfect guide for proficient C# programmers. This second edition is fully revised to cover new functional-inspired features in the most recent releases of C#, including tuples, async streams, pattern matching, and records. Each chapter is packed with awesome perspectives and epiphany moments on how functional programming can change the way you code. preface acknowledgments about this book about the author Part 1. Getting started 1 Introducing functional programming 1.1 What is this thing called functional programming? Functions as first-class values Avoiding state mutation Writing programs with strong guarantees 1.2 How functional a language is C#? The functional nature of LINQ Shorthand syntax for coding functionally Language support for tuples Pattern matching and record types 1.3 What you will learn in this book 2 Thinking in functions 2.1 What’s a function, anyway? Functions as maps Representing functions in C# 2.2 Higher-order functions (HOFs) Functions that depend on other functions Adapter functions Functions that create other functions 2.3 Using HOFs to avoid duplication Exercises 3 Why function purity matters 3.1 What is function purity? Purity and side effects Strategies for managing side effects Avoid mutating arguments 3.2 Enabling parallelization by avoiding state mutation Pure functions parallelize well Parallelizing impure functions Avoiding state mutation 3.3 Purity and testability Isolating I/O effects A business validation scenario Why testing impure functions is hard 3.4 Testing code that performs I/O Object-oriented dependency injection Testability without so much boilerplate 3.5 Purity and the evolution of computing Exercises Part 2. Core techniques 4 Designing function signatures and types 4.1 Designing function signatures Writing functions signatures with arrow notation How informative is a signature? 4.2 Capturing data with data objects Primitive types are often not specific enough Constraining inputs with custom types Writing honest functions Composing values into complex data objects 4.3 Modeling the absence of data with Unit Why void isn’t ideal Bridging the gap between Action and Func 5 Modeling the possible absence of data 5.1 The bad APIs you use every day 5.2 An introduction to the Option type 5.3 Implementing Option An idealized implementation of Option Consuming an Option Creating a None Creating a Some Optimizing the Option implementation 5.4 Option as the natural result type of partial functions Parsing strings Looking up data in a collection The smart constructor pattern 5.5 Dealing with null Why null is such a terrible idea Gaining robustness by using Option instead of null Non-nullable reference types? Bulletproof against NullReferenceException Exercises 6 Patterns in functional programming 6.1 Applying a function to a structure’s inner values Mapping a function onto a sequence Mapping a function onto an Option How Option raises the level of abstraction Introducing functors 6.2 Performing side effects with ForEach 6.3 Chaining functions with Bind Combining Option-returning functions Flattening nested lists with Bind Actually, it’s called a monad The Return function Relationship between functors and monads 6.4 Filtering values with Where 6.5 Combining Option and IEnumerable with Bind 6.6 Coding at different levels of abstraction Regular vs. elevated values Crossing levels of abstraction Map vs. Bind, revisited Working at the right level of abstraction Exercises 7 Designing programs with function composition 7.1 Function composition Brushing up on function composition Method chaining Composition in the elevated world 7.2 Thinking in terms of data flow Using LINQ’s composable API Writing functions that compose well 7.3 Programming workflows A simple workflow for validation Refactoring with data flow in mind Composition leads to greater flexibility 7.4 An introduction to functional domain modeling 7.5 An end-to-end server-side workflow Expressions vs. statements Declarative vs. imperative The functional take on layering Exercises Part 3. Functional designs 8 Functional error handling 8.1 A safer way to represent outcomes Capturing error details with Either Core functions for working with Either Comparing Option and Either 8.2 Chaining operations that may fail 8.3 Validation: A perfect use case for Either Choosing a suitable representation for errors Defining an Either-based API Adding validation logic 8.4 Representing outcomes to client applications Exposing an Option-like interface Exposing an Either-like interface Returning a result DTO 8.5 Variations on the Either theme Changing between different error representations Specialized versions of Either Refactoring to Validation and Exceptional Leaving exceptions behind? Exercises 9 Structuring an application with functions 9.1 Partial application: Supplying arguments piecemeal Manually enabling partial application Generalizing partial application Order of arguments matters 9.2 Overcoming the quirks of method resolution 9.3 Curried functions: Optimized for partial application 9.4 Creating a partial-application-friendly API Types as documentation Particularizing the data access function 9.5 Modularizing and composing an application Modularity in OOP Modularity in FP Mapping functions to API endpoints Comparing the two approaches 9.6 Reducing a list to a single value LINQ’s Aggregate method Aggregating validation results Harvesting validation errors Exercises 10 Working effectively with multi-argument functions 10.1 Function application in the elevated world Understanding applicatives Lifting functions An introduction to property-based testing 10.2 Functors, applicatives, and monads 10.3 The monad laws Right identity Left identity Associativity Using Bind with multi-argument functions 10.4 Improving readability by using LINQ with any monad Using LINQ with arbitrary functors Using LINQ with arbitrary monads The LINQ clauses let, where, and others 10.5 When to use Bind vs. Apply Validation with smart constructors Harvesting errors with the applicative flow Failing fast with the monadic flow Exercises 11 Representing state and change 11.1 The pitfalls of state mutation 11.2 Understanding state, identity, and change Some things never change Representing change without mutation 11.3 Using records to capture the state of domain entities Fine-grained control on record initialization Immutable all the way down 11.4 Separating data and logic 12 A short introduction to functional data structures 12.1 The classic functional linked list Common list operations Modifying an immutable list Destructuring any IEnumerable 12.2 Binary trees Common tree operations Structure sharing 12.3 In conclusion Exercises 13 Event sourcing: A functional approach to persistence 13.1 Thinking functionally about data storage Why data storage should be append-only Relax and forget about storing state 13.2 Event sourcing basics Representing events Persisting events Representing state Representing state transitions Reconstructing the current state from past events 13.3 Architecture of an event-sourced system Handling commands Handling events Adding validation Creating views of the data from events 13.4 Comparing different approaches to immutable storage Datomic vs. Event Store How event-driven is your domain? Part 4. Advanced techniques 14 Lazy computations, continuations, and the beauty of monadic composition 14.1 The virtue of laziness Lazy APIs for working with Option Composing lazy computations 14.2 Exception handling with Try Representing computations that may fail Safely extracting information from a JSON object Composing computations that may fail Monadic composition: What does it mean? 14.3 Creating a middleware pipeline for DB access Composing functions that perform setup/teardown A recipe against the pyramid of doom Capturing the essence of a middleware function Implementing the query pattern for middleware Adding middleware that times the operation Adding middleware that manages a DB transaction 15 Stateful programs and stateful computations 15.1 Programs that manage state Caching data in memory Refactoring for testability and error handling Stateful computations 15.2 A language for generating random data Generating random integers Generating other primitives Generating complex structures 15.3 A general pattern for stateful computations 16 Working with asynchronous computations 16.1 Asynchronous computations The need for asynchrony Representing asynchronous operations with Task Task as a container for a future value Handling failure An HTTP API for currency conversion If it fails, try a few more times Running asynchronous operations in parallel 16.2 Async streams Reading from a file as an async stream Consuming async streams functionally Consuming data from several streams Aggregation and sorting with async streams 17 Traversable and stacked monads 17.1 Traversables: Working with lists of elevated values Validating a list of values with monadic Traverse Harvesting validation errors with applicative Traverse Applying multiple validators to a single value Using Traverse with Task to await multiple results Defining Traverse for single-value structures 17.2 Combining asynchrony and validation (or any other two monadic effects) The problem of stacked monads Reducing the number of effects LINQ expressions with a monad stack 18 Data streams and the Reactive Extensions 18.1 Representing data streams with IObservable A sequence of values in time Subscribing to an IObservable 18.2 Creating IObservables Creating a timer Using Subject to tell an IObservable when it should signal Creating IObservables from callback-based subscriptions Creating IObservables from simpler structures 18.3 Transforming and combining data streams Stream transformations Combining and partitioning streams Error handling with IObservable Putting it all together 18.4 Implementing logic that spans multiple events Detecting sequences of pressed keys Reacting to multiple event sources Notifying when an account becomes overdrawn 18.5 When should you use IObservable? 19 An introduction to message-passing concurrency 19.1 The need for shared mutable state 19.2 Understanding message-passing concurrency Implementing agents in C# Getting started with agents Using agents to handle concurrent requests Agents vs. actors 19.3 Functional APIs, agent-based implementations Agents as implementation details Hiding agents behind a conventional API 19.4 Message-passing concurrency in LOB applications Using an agent to synchronize access to account data Keeping a registry of accounts An agent is not an object Putting it all together Appendix A. Working with previous version of C# Epilogue. What next? index Real world examples and practical techniques for functional programming in C# without the jargon and theory.In Functional Programming in C#, Second Edition you will learn how to: Use higher-order functions to reduce duplication and do more with less code Use pure functions to write code that is easy to test and optimize Write pleasant APIs that accurately describe your program's behavior Use dedicated types to handle nullability, system errors, and validation rules predictably and elegantly Write composable code without the overhead of an IoC container Functional Programming in C# has helped thousands of developers apply functional thinking to C# code. Its practical examples and spot-on treatment of FP concepts makes it the perfect guide for proficient C# programmers. This second edition is fully revised to cover new functional-inspired features in the most recent releases of C#, including tuples, async streams, pattern matching, and records. Each chapter is packed with awesome perspectives and epiphany moments on how functional programming can change the way you code. Purchase of the print book includes a free eBook in PDF, Kindle, and ePub formats from Manning Publications. About the technology Turbocharge your C# code. Good functional techniques will improve concurrency, state management, event handling, and maintainability of your software. This book gives you practical answers to why, how, and where to add functional programing into your C# coding practice. About the book Functional Programming in C#, Second Edition teaches functional thinking for real-world problems. It reviews the C# language features that allow you to program functionally and through many practical examples shows the power of function composition, data-driven programming, and immutable data structures. All code examples work with.NET 6 and C# 10. What's inside Higher-order functions reduce duplication and do more with less code Code based on pure functions is easy to test and optimize Write pleasant APIs that accurately describe your program's behavior Write a Web API in a functional style Monadic composition with LINQ About the reader For intermediate C# programmers. About the author Enrico Buonanno studied Computer Science at Columbia University and has over 15 years of experience as a developer, architect, and trainer. Table of Contents PART 1 GETTING STARTED 1 Introducing functional programming 2 Thinking in functions 3 Why function purity matters PART 2 CORE TECHNIQUES 4 Designing function signatures and types 5 Modeling the possible absence of data 6 Patterns in functional programming 7 Designing programs with function composition PART 3 FUNCTIONAL DESIGNS 8 Functional error handling 9 Structuring an application with functions 10 Working effectively with multi-argument functions 11 Representing state and change 12 A short introduction to functional data structures 13 Event sourcing: A functional approach to persistence PART 4 ADVANCED TECHNIQUES 14 Lazy computations, continuations, and the beauty of monadic composition 15 Stateful programs and stateful computations 16 Working with asynchronous computations 17 Traversable and stacked monads 18 Data streams and the Reactive Extensions 19 An introduction to message-passing concurrency
دانلود کتاب Functional Programming in C#, Second Edition