Functional PHP
Uncover the secrets of functional programming with PHP to ensure your applications are as great as they can be
Gilles Crettenand
BIRMINGHAM - MUMBAI
Functional PHP Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: February 2017 Production reference: 1100217
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78588-032-2 www.packtpub.com
Credits Author
Copy Editor
Gilles Crettenand
Safis Editing
Reviewer
Project Coordinator
Andrew Caya
Vaidehi Sawant
Commissioning Editor
Proofreader
Kunal Parikh
Safis Editing
Acquisition Editor
Indexer
Sonali Vernekar
Francy Puthiry
Content Development Editor
Graphics
Rohit Kumar Singh
Jason Monteiro
Technical Editor
Production Coordinator
Pavan Ramchandani
Arvindkumar Gupta
About the Author Gilles Crettenand is a passionate and enthusiastic software developer. He thrives when solving challenges and is always on the lookout for a better way to implement his solutions. He has a bachelor's degree in computer science from the School of Engineering and Management Vaud in Switzerland and has more than 6 years of experience as a web developer. Most of his professional career has been spent using PHP, developing a variety of applications ranging from accountability software to e-commerce solutions and CMS. At nights, however, he likes to try other languages, dabbling with Haskell, Scala, and more recently, PureScript, Elm, and Clojure. Being a certified scrum master, he understands the need to use the right tool for the job and maintaining a readable and maintainable codebase using the best techniques and practices available.
I’d like to thank my wife, Charlotte, for being understanding throughout the process of writing this book. My friend Loris also helped me a lot in putting some thoughts to paper and when I was struggling with some theoretical aspects. Kudos to my colleagues; without them, I wouldn’t be half the developer I am today. I will always be grateful for the hours of peer reviews and discussions about technical solutions and application architecture. I also want to thank the people from my coworking space who provided me with the much needed distraction when faced with a blank page. Thanks for the laughs and banter! Finally, I am appreciative to Packt for giving me the chance to write a book about my passions although I had no prior experience.
About the Reviewer Andrew Caya discovered his passion for computers at the age of 11 and started programming in GW-BASIC and QBASIC in the early 90s. He also did some software development in C, C++, and Perl, and some Linux system administration before becoming a PHP developer more than 7 years ago. He is now a professional contract programmer in Montreal, Canada, and a loving husband and father.
www.PacktPub.com For support files and downloads related to your book, please visit www.PacktPub.com. Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at
[email protected] for more details. At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Why subscribe? Fully searchable across every book published by Packt Copy and paste, print, and bookmark content On demand and accessible via a web browser
Customer Feedback Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at https://goo.gl/wYWIUc. If you'd like to join our team of regular reviewers, you can email us at
[email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Table of Contents Preface Chapter 1: Functions as First Class Citizens in PHP Before we begin Coding standards Autoloading and Composer Functions and methods PHP 7 scalar type hints Anonymous functions Closures Closures inside of classes Using objects as functions The Closure class Higher-order functions What is a callable? Summary
Chapter 2: Pure Functions, Referential Transparency, and Immutability Two sets of input and output Pure functions What about encapsulation? Spotting side causes Spotting side effects What about object methods? Closing words Immutability Why does immutability matter? Data sharing Using constants An RFC is on its way Value objects Libraries for immutable collections Laravel Collection Immutable.php
Referential transparency Non-strictness or lazy evaluation
1 7 8 8 8 9 10 13 14 15 16 17 17 17 20 21 22 24 24 25 27 28 30 30 31 31 32 36 37 39 39 39 40 42
Performance Code readability Infinite lists or streams
43 44 45 46 47 47 48
Code optimization Memoization PHP in all that? Summary
Chapter 3: Functional Basis in PHP
49
General advice Making all inputs explicit Avoiding temporary variables Smaller functions Parameter order matters The map function The filter function The fold or reduce function The map and filter functions using fold Folding left and right The MapReduce model Convolution or zip Recursion Recursion and loops Exceptions PHP 7 and exceptions Alternatives to exceptions Logging/displaying error message Error codes Default value/null Error handler The Option/Maybe and Either types Lifting functions The Either type Libraries The functional-php library How to use the functions General helpers Extending PHP functions Working with predicates Invoking functions Manipulating data Wrapping up
[ ii ]
49 50 50 51 51 52 54 55 58 59 60 60 62 66 68 70 72 72 73 75 77 78 86 88 89 90 90 91 91 92 92 93 94
The php-option library Laravel collections Working with Laravel's Collections
The immutable-php library Using immutable.php
Other libraries The Underscore.php library Saber Rawr PHP Functional Functional PHP functional programming Utils Non-standard PHP library
Summary
Chapter 4: Composing Functions
94 94 95 95 96 96 97 97 98 98 98 99 99 100 101
Composing functions Partial application Currying Currying functions in PHP Parameter order matters a lot! Using composition to solve real issues Summary
Chapter 5: Functors, Applicatives, and Monads Functors Identity function Functor laws Identity functor Closing words Applicative functors The applicative abstraction Applicative laws
101 103 104 107 109 112 117 118 119 120 121 123 124 124 126 128 128 129 129 129 129 130 132 135 136 136
Map Identity Homomorphism Interchange Composition Verifying that the laws hold
Using applicatives Monoids Identity law Associativity law
[ iii ]
Verifying that the laws hold What are monoids useful for? A monoid implementation Our first monoids Using monoids Monads Monad laws
136 138 139 140 143 144 146 146 146 147 147 148 149 150 151 151
Left identity Right identity Associativity Validating our monads
Why monads? Another take on monads A quick monad example Further reading Summary
Chapter 6: Real-Life Monads
153
Monadic helper methods The filterM method The foldM method Closing words Maybe and Either monads Motivation Implementation Examples List monad Motivation Implementation Examples
154 155 157 157 158 158 158 159 161 161 161 162 164 166 166 167 167 169 169 170 170 173 173
Where can the knight go?
Writer monad Motivation Implementation Examples Reader monad Motivation Implementation Examples State monad Motivation
[ iv ]
Implementation Examples IO monad Motivation Implementation Examples Summary
173 174 175 176 176 176 177
Chapter 7: Functional Techniques and Topics Type systems The Hindley-Milner type system Type signatures Free theorems Closing words Point-free style Using const for functions Recursion, stack overflows, and trampolines Tail-calls Tail-call elimination From recursion to tail recursion Stack overflows Trampolines Multi-step recursion The trampoline library
Alternative method Closing words Pattern matching Pattern matching in PHP Better switch statements Other usages
Type classes Algebraic structures and category theory From mathematics to computer science Important mathematical terms
Fantasy Land Monad transformers Lenses Summary
Chapter 8: Testing
179 180 180 181 184 185 186 188 190 190 191 192 195 196 198 199 200 201 202 205 206 208 209 212 214 217 218 219 219 220 222
Testing vocabulary
222
[v]
Testing pure functions All inputs are explicit Referential transparency and no side-effects Simplified mocking Building blocks Closing words Speeding up using parallelization Property-based testing What exactly is a property? Implementing the add function The PhpQuickCheck testing library Eris Closing words Summary
Chapter 9: Performance Efficiency
225 225 227 229 229 229 230 231 232 233 235 237 240 241 242
Performance impact Does the overhead matter? Let's not forget Can we do something? Closing words Memoization Haskell, Scala, and memoization Closing words Parallelization of computation Parallel tasks in PHP The pthreads extension Messaging queues Other options
Closing words Summary
Chapter 10: PHP Frameworks and FP Symfony Handling the request Database entities Embeddables Avoiding setters Why immutable entities? Symfony ParamConverter Maybe there is an entity
Organizing your business logic
[ vi ]
242 246 247 247 248 248 250 250 251 251 252 254 258 259 259 260 261 261 262 262 263 265 265 267 268
Flash messages, sessions, and other APIs with side-effects Closing words Laravel Database results Using Maybe
Getting rid of facades HTTP request Closing words Drupal Database access Dealing with hooks requiring side effects Hook orders Closing words WordPress Database access Benefits of a functional approach Closing words Summary
Chapter 11: Designing a Functional Application Architecture of a purely functional application From Functional Reactive Animation to Functional Reactive Programming Reactive programming Functional Reactive Programming Time traveling Disclaimer
Going further ReactiveX primer RxPHP Achieving referential transparency Summary
Chapter 12: What Are We Talking about When We Talk about Functional Programming What is functional programming all about? Functions Declarative programming Avoiding mutable state Why is functional programming the future of software development? Reducing the cognitive burden on developers
[ vii ]
269 269 270 271 272 273 274 275 275 276 276 277 278 278 279 279 280 281 282 283 285 286 287 288 289 289 290 291 293 294 295 296 296 297 298 298 298
Keeping the state away Small building blocks Locality of concerns Declarative programming
Software with fewer bugs Easier refactoring Parallel execution Enforcing good practices A quick history of the functional world The first years The Lisp family ML The rise of Erlang Haskell Scala The newcomers Functional jargon
Index
300 300 301 302 302 303 303 303 303 304 304 305 305 305 306 306 307 312
[ viii ]
Preface Functional programming is a paradigm that is present every year at conferences. The JavaScript community is probably one of the first that approached the subject, but the topic is now also discussed among the developers using various other languages such as Ruby, Python, and Java. PHP has most of the features that are needed to start using a functional approach for development. You have no reason to be left on the side, which is why this book proposes to teach you the fundamentals of functional programming. If you are completely new to functional programming or you want to refresh your basics and learn a bit about its history and benefits, I recommend that you start with the appendix. It is not the first chapter of the book as the content is not directly related to PHP, but it will help you put various topics in context and have a better idea of the topics covered in this book.
What this book covers Chapter 1, Functions as First Class Citizen in PHP, discusses how functional programming,
as the name suggests, revolves around functions. In this chapter, you will learn the about the various way they can be declared and used in PHP. Chapter 2, Pure Functions, Referential Transparency, and Immutability, covers the three
concepts that are the cornerstone of any functional code base. You will learn what they are about and how to apply them to our benefit. Chapter 3, Functional Basis in PHP, discusses how functional programming, like any
paradigm, rests upon a few core concepts. This chapter will present them in a simple fashion before going further. Chapter 4, Composing Functions, describes how functions are often used as a building block
using function composition. In this chapter, you will learn how to do it in PHP what it is important to keep in mind when doing so.
Chapter 5, Functors, Applicatives, and Monads, starts with easier concepts, such as the functor
and the applicative, and we will build up our knowledge to finally present the monad in a light that should dispel some of the fear floating around this term.
Preface Chapter 6, Real-life Monads, helps you learn about some real-life usage of the monad
abstraction and how it can be used to write better code.
Chapter 7, Functional Techniques and Topics, brushes upon topics such as type systems,
pattern matching, point-free style, and others from the vast field of functional programming.
Chapter 8, Testing, teaches you that functional programming not only helps with writing
code that is easier to understand and maintain, but it is also great to facilitate testing.
Chapter 9, Performance Efficiency, lets you know that using functional techniques in PHP
has a cost. We will first discuss it and then see how it can help in other performance-related topics. Chapter 10, PHP Frameworks and FP, introduces a technique that can be applied to improve
your code in any project, as there is currently now dedicated framework for functional programming in PHP.
Chapter 11, Designing a Functional Application, will present you with some advice if you
want to develop a whole application using the most functional code possible. You will also learn about Functional Reactive Programing and the RxPHP library. Appendix, What are We Talking about When We Talk about Functional Programming?, is a
presentation and history of functional programming alongwith its benefits and a glossary. It’s really the first part of the book you should read, but as we don’t approach the subject from the PHP angle, it is presented as an appendix.
What you need for this book You will need to have access to a computer with PHP installed. It will be easier if you know how to use the command line, but all examples should also work in a browser with maybe some small adaptations. While learning functional programming, I also recommend the usage of a Read-Eval-PrintLoop (REPL). I personally used Boris when writing this book. You can find it at https://gi thub.com/borisrepl/boris. Another great option is PsySH (http://psysh.org). Although not at all mandatory, a REPL will allow you to quickly test your ideas and play around with the various concepts that will be presented in this book without having to juggle between your editor and command line.
[2]
Preface
I also assume you have Composer available and that you know how to use it to install new packages; if not, you can find it at https://getcomposer.org. Multiple libraries will be presented throughout the book and the preferred way to install them is using composer. All the code written in the book was tested on PHP 7.0, which is the de facto recommended version. It should, however, also run on any newer version. Running most of the examples should also be fine on PHP 5.6 after making some minor adaptations. We will use the new scalar type hinting feature introduced in PHP 7.0 throughout the book, but if you remove those, the code should be readily compatible with lower versions.
Who this book is for This book requires no knowledge of functional programming; prior programming experience is, however, required. Also, basic concepts from object-oriented programming will not be covered in depth. Deep knowledge of the PHP language is not mandatory, as uncommon syntax will be explained. The book should be understandable to someone who hasn't written a single line of PHP code, with some effort. This book can be considered as a beginner book about functional programming in PHP, meaning that we will build knowledge incrementally. However, the topic being pretty vast and the limited page count, we will move quickly at times. This is why I encourage you to play with the variously presented concepts as we learn them and take some time at the end of each chapter to make sure you understood it correctly.
Conventions In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning. Code words in the text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "The next lines of code read the link and assign it to the BeautifulSoup function."
[3]
Preface
A block of code is set as follows: