Programming F# 3.0 Chris Smith Programming F# 3.0 by Chris Smith Copyright © 2013 Chris Smith. 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://my.safaribooksonline.com). For more information, contact our corporate/ institutional sales department: 800-998-9938 or [email protected]. Editor: Rachel Roumeliotis Proofreader: Absolute Service, Inc. Production Editor: Holly Bauer Indexer: Lucie Haskins Copyeditor: Jasmine Kwityn Cover Designer: Karen Montgomery Interior Designer: David Futato Illustrator: Rebecca Demarest October 2009: First Edition October 2012: Second Edition Revision History for the Second Edition: 2012-10-08 First release See http://oreilly.com/catalog/errata.csp?isbn=9781449320294 for release details. Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. Programming F# 3.0, the image of a bullfinch, and related trade dress are trademarks of O’Reilly Media, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trade mark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and authors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein. ISBN: 978-1-449-32029-4 [LSI] Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi Part I. Multiparadigm Programming 1. Introduction to F#. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Getting to Know F# 3 Visual Studio 11 4 Your Second F# Program 5 Values 6 Whitespace Matters 6 .NET Interop 8 Comments 8 F# Interactive 9 Managing F# Source Files 11 2. Fundamentals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Primitive Types 15 Numeric Primitives 16 Arithmetic 17 Conversion Routines 19 BigInteger 19 Bitwise Operations 20 Characters 20 Strings 21 Boolean Values 22 Comparison and Equality 24 Functions 24 Type Inference 25 Generic Functions 27 iii Scope 27 Control Flow 29 Core Types 31 Unit 32 Tuple 32 Lists 34 Aggregate Operators 39 Option 42 Printf 44 Organizing F# Code 46 Modules 46 Namespaces 47 Program Startup 48 3. Functional Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Understanding Functions 52 Immutability 53 Function Values 54 Recursive Functions 58 Symbolic Operators 60 Function Composition 61 Pattern Matching 68 Match Failure 69 Named Patterns 70 Matching Literals 70 when Guards 71 Grouping Patterns 72 Matching the Structure of Data 73 Outside of Match Expressions 74 Alternate Lambda Syntax 75 Discriminated Unions 76 Using Discriminated Unions for Tree Structures 78 Pattern Matching 79 Methods and Properties 81 Records 81 Cloning Records 82 Pattern Matching 83 Type Inference 83 Methods and Properties 84 Lazy Evaluation 85 Lazy Types 85 Sequences 86 iv | Table of Contents Sequence Expressions 87 Seq Module Functions 88 Aggregate Operators 89 Queries 90 Query Expressions 92 Query Operators 92 4. Imperative Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Understanding Memory in .NET 98 Value Types Versus Reference Types 99 Default Values 99 Reference Type Aliasing 101 Changing Values 102 Reference Cells 103 Mutable Records 104 Units of Measure 105 Defining Units of Measure 107 Converting Between Units of Measure 108 Generic Units of Measure 109 Arrays 110 Indexing an Array 111 Array Slices 113 Creating Arrays 114 Pattern Matching 115 Array Equality 115 Array Module Functions 116 Multidimensional Arrays 117 Mutable Collection Types 119 List<'T> 119 Dictionary<'K,'V> 121 HashSet<'T> 122 Looping Constructs 123 While Loops 123 For Loops 124 Exceptions 126 Handling Exceptions 127 Reraising Exceptions 130 Defining Exceptions 130 5. Object-Oriented Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Programming with Objects 133 The Benefits of OOP 133 Table of Contents | v Where OOP Breaks Down 134 Understanding System.Object 134 Common Methods 135 Object Equality 137 Generated Equality 139 Understanding Classes 141 Explicit Construction 141 Implicit Class Construction 143 Generic Classes 144 The Self Identifier 146 Methods and Properties 146 Properties 146 Setting Properties in the Constructor 149 Methods 149 Static Methods, Properties, and Fields 151 Method Overloading 153 Accessibility Modifiers 154 Inheritance 157 Method Overriding 158 Categories of Classes 160 Casting 161 6. .NET Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 The .NET Platform 165 The CLI 165 Garbage Collection 166 Interfaces 168 Using Interfaces 169 Defining Interfaces 170 Object Expressions 171 Object Expressions for Interfaces 172 Object Expressions for Derived Classes 173 Extension Methods 174 Extending Modules 175 Enumerations 176 Creating Enumerations 176 Conversion 178 When to Use an Enum Versus a Discriminated Union 178 Structs 179 Creating Structs 180 Restrictions 182 vi | Table of Contents When to Use a Struct Versus a Record 182 Part II. Programming F# 7. Applied Functional Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Active Patterns 185 Single-Case Active Patterns 187 Partial Active Patterns 187 Parameterized Active Patterns 189 Multicase Active Patterns 190 Using Active Patterns 192 Using Modules 195 Converting Modules to Classes 195 Intentional Shadowing 198 Controlling Module Usage 200 Mastering Lists 201 List Operations 202 Using Lists 203 Tail Recursion 205 Understanding the Stack 206 Introducing Tail Recursion 208 Tail-Recursive Patterns 210 Programming with Functions 214 Partial Function Application 214 Eliminating Redundant Code 215 Closures 216 Functional Patterns 218 Memoization 218 Mutable Function Values 220 Lazy Programming 221 Functional Data Structures 223 Functional Set 223 Functional Map 225 8. Applied Object-Oriented Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Operators 227 Operator Overloading 227 Indexers 229 Adding Slices 231 Generic Type Constraints 234 Delegates and Events 237 Table of Contents | vii Defining Delegates 238 Combining Delegates 240 Events 241 Creating Events 241 The Event<_,_> Class 243 The Observable Module 244 Creating .NET Events 248 9. Asynchronous and Parallel Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Working with Threads 252 Spawning Threads 253 The .NET Thread Pool 254 Sharing Data 255 Asynchronous Programming 259 Asynchronous Workflows 262 The Async Library 263 Async Operations 268 Custom Async Primitives 269 Limitations 270 Parallel Programming 271 Parallel.For 271 The Array.Parallel Module 272 Task Parallel Library 273 Primitives 274 Concurrent Data Structures 278 10. Scripting. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 F# Script Files 284 Directives 284 General Directives 285 F# Script-Specific Directives 286 F# Script Recipes 288 Colorful Output 288 Producing Sound 289 Walking a Directory Structure 289 Starting Processes Easily 290 Automating Microsoft Office 291 11. Data Processing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 Indexing 296 The Index Data Structure 296 MapReduce Processing 299 viii | Table of Contents