Simon J. Painter Functional Programming with C# Create More Supportable, Robust, and Testable Code
.NET “An indispensable companion for developers seeking to elevate their code to new heights of clarity and productivity.” —Gerald Versluis Senior Software Engineer at Microsoft Functional Programming with C# Twitter: @oreillymedia linkedin.com/company/oreilly-media youtube.com/oreillymedia After decades of relative obscurity, functional programming is finally coming into its own. With concise, easy-to-read code that supports asynchronous, concurrent processing, aspects of functional programming have begun to appear in several traditionally object-oriented languages such as C# and Java. This practical book shows C# programmers how to use functional programming features without having to navigate an entirely new language. Because of the runtime environment common to C# and F# languages, it’s possible to use most of F#’s functional features in C# as well. Author Simon J. Painter explains how you can write functional code in C# right away, without having to install dependencies or features newer than .NET 3. You’ll learn why functional programming concepts can bring immediate benefit to your work. • Learn what functional programming is and how it originated • Discover features of the functional paradigm using a more familiar language • Start coding functionally in C# right away, without relying on third-party libraries • Write code that’s more robust, less error prone, and easier to test • Examine less conventional ways to look at structures available in C# • Explore the practicalities of using functional C# in a business environment Simon J. Painter has been developing professionally since 2005, having worked with every version of .NET in about a dozen different industries. He appears regularly at user groups and conferences to give talks on functional programming and general .NET topics. Simon lives in the United Kingdom with his wife and children. US $79.99 CAN $99.99 ISBN: 978-1-492-09707-5
Praise for Functional Programming with C# Simon is my go to for all things functional programming. This book perfectly reflects his knowledge, expertly guiding the reader through the topic. —Pete Gallagher, Microsoft Meetup Organizer and Development Manager at Avanade UK Functional Programming with C# takes a pragmatic view—building real solutions from functional aspects built into C# and techniques that bring even more functionality to C#. —Kathleen Dollard, Principal Program Manager, .NET, at Microsoft If you’re diving into the world of functional programming and want to use C#, Simon Painter’s book is a clear and helpful guide. He doesn’t just throw around jargon or get lost in abstract concepts. Instead, Simon breaks down challenging topics into simple terms, making them easy to understand. One of the standout features of the book is its examples. Simon offers great real-world examples that show the true benefits of functional programming in C#. These aren’t just abstract ideas; they’re practical tools and techniques you can use in your projects right away. —Chris Ayers, Senior Customer Engineer at Microsoft This book is an excellent guide on how to think functionally and better utilize the functional features of C# to write simpler, more robust code. —Ian Russell, Author of Essential F#
Functional Programming with C# is a fun read for someone who wants to take their programming game to the next level. Simon creates an easy to follow way to learn and implement functional programming while keeping it entertaining. By embracing the diverse and practical examples, my code has more conciseness and readability. This book is suitable for both those new to functional programming and individuals seeking to harness C#’s robust capabilities to the fullest. —Alex Wild, Senior Software Engineer An amazing mixture of clever examples, powerful concepts, and dad jokes. —Matthew Fletcher, Senior Software Engineer at Bravissimo A great guide that seamlessly connects the world of functional programming with the robust capabilities of C#. An indispensable companion for developers seeking to elevate their code to new heights of clarity and productivity. —Gerald Versluis, Senior Software Engineer at Microsoft Simon has joined me numerous times both at the .NET user-group I run and also on my podcast, talking about functional programming. Knowing how well Simon can articulate problems and teach solutions, I have no doubt that this book will be equally as enlightening to its readers as his talks have been to our community. —Dan Clarke, Independent Software Consultant, and Host of The Unhandled Exception Podcast Functional programming without the fear. My new go to resource for those exploring functional programming with C#. —Matt Eland, Microsoft MVP and Senior Solutions Developer II at Leading EDJE Functional programming? Does that mean the rest of us are dysfunctional? —Richard Campbell, Host of the .NET Rocks! Podcast Functional Programming with C# gives you a gentle but great introduction into the world of functional programming. Simon, in his typical style, explains the concepts thoroughly. I highly recommend this book if you want to understand the concepts of functional programming. —Poornima Nayar, Freelance .NET Developer and Microsoft MVP
Simon Painter makes functional programming easily accessible and applicable to C# developers new and experienced, even those as intransigent as myself, in Functional Programming with C#. —Jimmy Bogard, Independent Consultant Simon explains the benefits of functional programming succinctly, using helpful code samples to illustrate topics ranging from FP basics to more advanced features, as well as how to apply them in C#. —Isaac Abraham, Author of F# in Action As I was new to developing (+25y infra background), reading Functional Programming with C# was a hard nut to crack at first. When Simon described the concepts using a “baking cakes” analogy, it all started to make sense. Closing the book by building a Martian Trail game to the year 2147 was a great finish of the learning experience, and another analogy for the stretch of knowledge I picked up by going through this book. —Peter De Tender, Technical Trainer at Microsoft
(This page has no text content)
Simon J. Painter Functional Programming with C# Create More Supportable, Robust, and Testable Code Boston Farnham Sebastopol TokyoBeijing
978-1-492-09707-5 [LSI] Functional Programming with C# by Simon J. Painter Copyright © 2023 Simon J. Painter. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://oreilly.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com. Acquisitions Editor: Brian Guerin Development Editor: Jill Leonard Production Editor: Gregory Hyman Copyeditor: Sharon Wilkey Proofreader: Kim Cofer Indexer: Sue Klefstad Interior Designer: David Futato Cover Designer: Karen Montgomery Illustrator: Kate Dullea September 2023: First Edition Revision History for the First Edition 2023-09-12: First Release See https://www.oreilly.com/catalog/errata.csp?isbn=9781492097075 for release details. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Functional Programming with C#, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. The views expressed in this work are those of the author, and do not represent the publisher’s views. While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights.
To my wife, Sushma Mahadik. My Billi. Also to my two daughters, Sophie and Katie. Your daddy loves you, girls.
(This page has no text content)
Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 What Is Functional Programming? 2 Is It a Language, an API, or What? 2 The Properties of Functional Programming 3 Baking Cakes 13 An Imperative Cake 13 A Declarative Cake 14 Where Does Functional Programming Come From? 14 Who Else Does Functional Programming? 16 Pure Functional Languages 16 Is It Worth Learning a Pure Functional Language First? 17 What About F#? Should I Be Learning F#? 18 Multiparadigm Languages 20 The Benefits of Functional Programming 21 Concise 21 Testable 22 Robust 22 Predictable 22 Better Support for Concurrency 23 Reduced Code Noise 24 The Best Places to Use Functional Programming 24 Where You Should Consider Using Other Paradigms 25 How Far Can We Take This? 25 Monads Actually, Don’t Worry About This Yet 26 Summary 26 v
Part I. What Are We Already Doing? 2. What Can We Do Already?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Getting Started 29 Writing Your First Functional Code 30 A Nonfunctional Film Query 30 A Functional Film Query 31 Focusing on Results-Oriented Programming 32 Understanding Enumerables 34 Preferring Expressions to Statements 38 The Humble Select 38 Many to One: The Subtle Art of Aggregation 42 Customized Iteration Behavior 43 Making Your Code Immutable 46 Putting It All Together: A Complete Functional Flow 48 Taking It Further: Develop Your Functional Skills 52 Summary 53 3. Functional Coding in C# 7 and Beyond. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Tuples 55 Pattern Matching 56 Procedural Bank Accounts 56 Pattern Matching in C# 7 59 Pattern Matching in C# 8 60 Pattern Matching in C# 9 62 Pattern Matching in C# 10 62 Pattern Matching in C# 11 63 Read-Only Structs 64 Init-Only Setters 66 Record Types 67 Nullable Reference Types 70 The Future 72 Discriminated Unions 73 Active Patterns 74 Summary 74 4. Work Smart, Not Hard with Functional Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 It’s Time to Get Func-y 78 Funcs in Enumerables 78 A Super-Simple Validator 79 Pattern Matching for Old Versions of C# 81 Make Dictionaries More Useful 85 vi | Table of Contents
Parsing Values 87 Custom Enumerations 89 Query Adjacent Elements 89 Iterate Until a Condition Is Met 92 Summary 94 Part II. Into the Belly of the Functional 5. Higher-Order Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 A Problem Report 98 Thunks 101 Chaining Functions 104 Fork Combinator 106 Alt Combinator 108 Compose 109 Transduce 112 Tap 114 Try/Catch 115 Handling Nulls 119 Update an Enumerable 121 Summary 123 6. Discriminated Unions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Holiday Time 125 Holidays with Discriminated Unions 127 Schrödinger’s Union 129 Naming Conventions 130 Database Lookup 133 Sending Email 135 Console Input 136 Generic Unions 140 Maybe 140 Result 141 Maybe Versus Result 142 Either 145 Summary 146 7. Functional Flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Maybe, Revisited 147 Maybe and Debugging 152 Map() Versus Bind() 153 Table of Contents | vii
Maybe and the Primitives 154 Maybe and Logging 157 Maybe and Async 160 Nested Maybes 161 The Laws 164 Left Identity Law 164 Right Identity Law 164 Associativity Law 165 Reader 165 State 168 Maybe a State? 170 Examples You’re Already Using 171 Enumerable 171 Task 172 Other Structures 173 A Worked Example 175 Summary 177 8. Currying and Partial Application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 Currying and Large Functions 180 Currying and Higher-Order Functions 184 Currying in .NET 185 Partial Application 187 Partial Application in .NET 188 Summary 189 9. Indefinite Loops. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 Recursion 194 Trampolining 196 Custom Iterator 200 Understanding the Anatomy of an Enumerator 200 Implementing Custom Enumerators 201 Indefinitely Looping Enumerables 203 Using Indefinite Iterators 206 Summary 208 10. Memoization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 Bacon Numbers 209 Implementing Memoization in C# 214 Summary 216 viii | Table of Contents
Part III. And Out the Other Side 11. Practical Functional C#. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 Functional C# and Performance 219 Baseline: An Imperative Solution 221 Performance Results 222 What Does All of This Mean? 231 Functional C# Concerns and Questions 233 How Functional Should I Make My Codebase? 233 How Should I Structure a Functional C# Solution? 234 How Do I Share My Functional Methods Among Applications? 234 Did You Order This Pizza? 235 How Do I Convince My Teammates to Do This Too? 235 Is It Worth Including F# Projects in My Solution? 237 Will Functional Coding Solve All My Problems? 238 Connery, Moore, or Craig? 238 How Do I Think Through a Problem Functionally? 238 What If There’s No Way to Make a Bit of Code as High-Performant as I’d Like with Functional-Style Code? 239 Summary 239 12. Existing Functional Programming Libraries in NuGet. . . . . . . . . . . . . . . . . . . . . . . . . . 241 OneOf 242 LanguageExt 245 Option 245 Either 247 Memoization 247 Reader 248 State 249 LanguageExt Wrap-up 249 Functional.Maybe 250 CSharpFunctionalExtensions 252 Maybe 252 Result 253 Fluent Assertions 254 CSharpFunctionalExtensions Wrap-up 254 The F# Programming Language 254 Summary 254 13. The Martian Trail. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 Story 257 Technical Detail 258 Table of Contents | ix
Creating the Game 260 The Solution 260 Communications 261 Want to Learn How to Play? 262 The Inventory Setup 263 The Game Loop 271 Summary 284 14. Conclusion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 What Kind of Day Has It Been? 287 Where Do I Go from Here? 288 More Functional C# 288 Learn F# 289 Pure Functional Languages 289 What About You? 290 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 x | Table of Contents
Preface I attend developers’ conferences as often as I’m able and have noticed a trend. Each year, there always seems to be more content about functional programming (FP), not less. Often an entire track is dedicated to it, and the other talks include FP content somewhere as a talking point. FP is slowly but surely becoming a big deal. Why is that? Because FP is one of the greatest innovations in the history of software development. It’s also cool. Fun as well. With the growth of concepts like containerization and serverless applications, FP isn’t just a bit of fun for developers’ free-time projects; it’s not a fad that’ll be forgotten in a few years. It has real benefit to bring to our stakeholders. Further, in the .NET world, several additional factors are at play. Mads Torgerson, the C# lead designer, is himself a fan of FP, and one of the major driving forces behind the adoption of the functional paradigm into .NET. There’s also F#, the .NET functional language. Because F# and C# share a common runtime, many functional features requested by the F# team often become available in C# in some form as well. The big questions remain, though: What is FP? And will I need to learn an entire new programming language just to be able to use it? The good news is that if you’re a .NET developer, you don’t need to spend large chunks of your own time learning a new technology just to stay up-to-date. You don’t even have to invest in another third-party library to add to your application’s dependencies: FP is possible with out-of-the-box C# code, albeit with a little tinkering around. This book introduces all the fundamental concepts of FP, demonstrates their benefits, and describes how they might be achieved in C#—not just for your own hobby programming, but with a real eye toward bringing immediate benefit to your work life as well. xi
These benefits include things such as the following: • Code that is cleaner, tidier, and easier to read • An easier-to-maintain codebase • Applications that are significantly less likely to suffer from unhandled exceptions and their unpredictable consequences • A codebase that’s easier to write automated unit tests for All this and more! Who Should Read This Book? This book is intended for developers—whether professional, student, or hobbyist— who already have a basic grounding in C#. You don’t need to be an expert but do need to be familiar with the basics and feel comfortable putting together at least a relatively simply C# application. Some more advanced .NET topics are covered, but I’ll provide explanations when they come up. This book has been written with a few categories of people in mind: • Those of you who have learned the basics of C# but want to find ways to take your learning further via more advanced techniques for writing better, more robust code. • .NET developers who have heard of FP and perhaps even know what it is, but want to know how to get started writing code that way in C#. • F# developers looking for ways to keep using the functional toys you’re used to. • Those migrating to .NET from another functional, or functional-supporting, language (like Java). • Anyone who really, truly loves coding. If you spend all day writing code in the office, then come home to write more for fun, this book is probably for you. Why I Wrote This Book I’ve been interested in programming for as long as I can remember. When I was a young boy, we had a ZX Spectrum, a British home computer developed by Sinclair Research in the early ’80s. If anyone remembers the Commodore 64, it was a bit like xii | Preface
1 It had eight base colors and a bright version of each. One was black, though, and how on earth can you have bright black? So…15. that but far more primitive. It had just 15 colors and a screen resolution of 256 × 192.1 I had the more advanced model with 48K of memory, though my Dad had the earlier machine, the ZX81, which had a single kilobyte of memory available (and rubber keys). It couldn’t even have colored-in character sprites, just areas of the screen, so your game avatar would change color to that of whatever they were standing in front of. In short, it was pure awesome on toast. One of the best things about it was its OS that effectively consisted of a text-based programming interface, and code was required to load a game (from a cassette tape, with the command LOAD ""), but magazines and books for kids were available with code you could enter yourself for games. It was from these that I developed my lasting obsession with the mysteries of computer code. Thanks so much, Usborne Publishing! When I was around 14 years old or so, a computer-based careers advice program at school suggested I could think about taking up a career in software development. This is the first time I realized that you could take this silly hobby and turn it into something that you could actually make money from! After university was over, it was time to get a proper job, and that was where I got my first exposure to C#. So the next step, I supposed, was to learn how to develop code properly. Easy, right? I’ll be honest, nearly two decades on, I’m still trying to work that out. One of the big turning points for me in my programming career was attending a developers’ conference in Norway and finally starting to understand what this functional programming thing I’d been hearing about was actually about. Functional code is elegant, concise, and easy to read in a way that other forms of code just don’t seem to be. As with any type of code, writing horrible-looking codebases is still possible, but the coding still fundamentally feels like it’s finally being done properly, in a way that I’ve never really felt from other styles of coding. Hopefully, after reading this book, you’ll not only agree but also be interested in searching out the many other avenues that exist out there for exploring it further. Navigating This Book This is how I’ve organized this book: • Chapter 1 is the introduction and covers what you can do right now to start coding functionally in C#, without having to reference a single new NuGet package, use a third-party library, or hack around with the language. Nearly all Preface | xiii
2 But if this were a novel, you can guarantee it’d be a murder mystery, and the butler would have done it! the examples in this chapter work with just about every version of C# since version 3. This chapter presents the very first steps into FP, all fairly easy code, which sets the groundwork for what’s to come. • Part I, “What Are We Already Doing?” (Chapters 2 through 4), is about ways to adopt a few functional ideas into your daily C# coding without needing to do anything that’s fundamentally all that unfamiliar. Many of the code samples are straightforward, out-of-the-box C#. Try these chapters if you’ve never heard of FP before and want a nice, gentle introduction. Think of it as dipping your toes in the water to see if you’re interested in going for a swim. • Part II, “Into the Belly of the Functional” (Chapters 5 through 10), is where the gloves come off, and I start introducing some “proper” functional concepts. Don’t panic, though; I’m going to be taking the gentle slope up to the summit, and will introduce ideas slowly and in easy-to-digest, bite-size pieces. • Part III, “And Out the Other Side” (Chapters 11 through 14), wraps up and consolidates everything you’ve learned so far, as well as suggests where you might consider ways to continue learning further. Feel free to dive in at the level you feel ready for. This isn’t a novel;2 read the chapters in the order that makes sense to you. Conventions Used in This Book The following typographical conventions are used in this book: Italic Indicates new terms, URLs, email addresses, filenames, and file extensions. Constant width Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords. This element signifies a general note. xiv | Preface
Comments 0
Loading comments...
Reply to Comment
Edit Comment