39,59 €
Functional programming is a paradigm specifically designed to deal with the complexity of software development in large projects. It helps developers to keep track of the interdependencies in the code base and changes in its state in runtime. Mastering Functional Programming provides detailed coverage of how to apply the right abstractions to reduce code complexity, so that it is easy to read and understand.
Complete with explanations of essential concepts, practical examples, and self-assessment questions, the book begins by covering the basics such as what lambdas are and how to write declarative code with the help of functions. It then moves on to concepts such as pure functions and type classes, the problems they aim to solve, and how to use them in real-world scenarios. You’ll also explore some of the more advanced patterns in the world of functional programming such as monad transformers and Tagless Final. In the concluding chapters, you’ll be introduced to the actor model, which you can implement in modern functional languages, and delve into parallel programming.
By the end of the book, you will be able to apply the concepts of functional programming and object-oriented programming (OOP)in order to build robust applications.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 492
Veröffentlichungsjahr: 2018
Copyright © 2018 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 or its dealers and distributors, will be held liable for any damages caused or alleged to have been 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.
Commissioning Editor: Aaron LazarAcquisition Editor: Sandeep MishraContent Development Editor: Manjusha MantriTechnical Editor: Abhishek SharmaCopy Editor:Safis EditingProject Coordinator: Prajakta NaikProofreader: Safis EditingIndexer: Mariammal ChettiyarGraphics: Jisha ChirayilProduction Coordinator: Shantanu Zagade
First published: August 2018
Production reference: 1300818
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78862-079-6
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
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.
Anatolii Kmetiuk is a Functional Programming and Data Science Freelance Developer. During his programming career, he has worked on Scala projects involving parallel computing, web APIs, SaaS, and data engineering. His areas of expertise include using applications of pure functional programming to build fault-tolerant, reactive systems, as well as parallel computing. Another area of his focus is machine learning and natural language processing.
Marco Borst is an independent programmer with more then 20 years of experience programming systems that yield useful applications. He teaches development teams alternative points of view regarding the applicability and limits of our functional abstractions. Stoked to be the most pragmatic person in the room, Marco shares his appreciation that, out of a multitude of daily choices to do either A or B, the least useless choice is often to do neither A nor B. It is a difficult choice to act upon. Being an engineer by education, a programmer by experience, and a communicator because nature forced him to be, Marco is inclined to share his craft with others and is positively thrilled when able to learn from others as well.
André van Delft is an independent computer science researcher in the Netherlands. Having studied mathematics and business administration, he has made a living as a consultant and scientist in various organizations. His main project is SubScript, which extends Scala with the so called Algebra of Communicating Processes, a concurrency theory from the 1980s, which he has presented at various conferences, such as Lambda Days, LambdaConf, and FLOPS. His product, SlideMight, may be the first off-the-shelf software that is partially powered with the Algebra of Communicating Processes.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Mastering Functional Programming
Dedication
Packt Upsell
Why subscribe?
PacktPub.com
Contributors
About the author
About the reviewers
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
The Declarative Programming Style
Technical requirements
Principles of declarative programming
Example – go-to versus loops
Example – nested loop
Don't Repeat Yourself (DRY)
Declarative versus imperative collections
Filtering
Declarative programming in other languages
Summary
Questions
Functions and Lambdas
Functions as behavior
Functions in functional programming
Higher-order functions
Understanding lambda functions
The concept of functions in different programming languages
Summary
Questions
Functional Data Structures
Collections framework
Imperative collections
Functional collections
Algebraic approach
Effect types
Try
Option
Data structures in different programming languages
Summary
Questions
Further reading
The Problem of Side Effects
Side effects
Mutable states
Pure functions
Referential transparency
Generally encountered side effects
Error
Absence of result
Delay and asynchronous computations
Logging
Input-output operations
But how do we get rid of the side effects?
The pure functional paradigm in different languages
Summary
Questions
Effect Types - Abstracting Away Side Effects
Turning effects into data
The sequential combination of effects with Monads
Introducing the map function
Introducing the flatMap function
Summary
Questions
Effect Types in Practice
Future
Motivation and the imperative example
Abstraction and the functional example
Composing Futures
flatMap generalized
Either
Reader
Functional solution
Summary
Questions
The Idea of the Type Classes
Rich Wrapper pattern
Motivation
Implicit conversions
Rich Wrapper
The Type Class pattern
Interpretation of the Type Class pattern
Injectable interfaces
Toolboxes
Type classes in different languages
Summary
Questions
Basic Type Classes and Their Usage
A motivation for organizing type classes into systems and libraries
The Cats library for purely functional programming
The structure of the library
Core
Type class hierarchy
Abstract methods
Concrete methods
Laws
Syntax
Instances
Data
Infrastructure synergy
Type classes
Monad
Writer effect type
The tailRecM method
Functor
Applicative
Motivation
Applicative type class
Implementation of the type class
Monoid
Implementation for Either
MonoidK
Traverse
Summary
Questions
Libraries for Pure Functional Programming
Cats effect
ProductR
IO – the concurrence data type
Referential transparency
Inversion of control
Asynchrony with IO
Blocking example
Concurrency infrastructure
Running tasks in bunches
Heavy load with blocking
Synchronous tasks
Constructing asynchronous tasks
Asynchronous API
Asynchronous example
Fibers
The computation
IO combination without Fibers
IO combination with Fibers
Canceling Fibers
Bracket
Server-side programming
The architecture of a server-side application
Communication protocol
The software architecture of a server
Example specification
Orchestration and infrastructure
Docker
Docker-compose
Dockerfiles
Backend architecture
Model
Database layer
Server-side programming
Querying the server
Summary
Questions
Patterns of Advanced Functional Programming
Monad Transformers
The specialization of effect types
An application with multiple side effects
Asynchrony
The side effect of errors
Monad Transformers
Generalizing the pattern
Tagless Final
Programming to capabilities
Implementations
Execution semantics abstraction
Computation as a value
Free Monad
Type-level programming
A naive implementation of the heterogeneous list
Type-level solution to the heterogeneous list problem
Reclusive implicit resolution
Debugging type-level computations
Libraries for type-level programming
Summary
Questions
Introduction to the Actor Model
Overview of parallelism solutions
Traditional model synchronization on monitors
Synchronization
Problems with the traditional model – race conditions and deadlocks
The actor model as a replacement for the traditional model
Deadlock example revisited
Summary
Questions
The Actor Model in Practice
Akka overview
Principles of Akka
Encapsulation
Messaging
No leaking of mutable state
Fault-tolerance and supervision
Messaging guarantees
Asynchrony
Defining, creating, and messaging actors
Callbacks
Supervision
Context and references
Managing the actor hierarchy
Managing the life cycle
Supervision
Creating actors
Actor parameters
Working with actor systems
Task specification
Implementation
Summary
Questions
Use Case - A Parallel Web Crawler
Problem statement
The graph structure of the web
Collecting information from the graph
Parallel nature of the task
Sequential solution
A parallel solution with Akka
Strategy
Implementation
Caveats
Visited links
Fault tolerance
Counting the responded actors
Real-world side effects
Summary
Introduction to Scala
Motivation for using Scala
Scala infrastructure
Scala interpreter
SBT build tool
Variables and functions
Control structures
If and While
For
Pattern matching
Partial functions
Inheritance model
Classes
Traits
Singleton objects
Summary
Assessments
Chapter 1
Chapter 2
Chapter 3
Chapter 4
Chapter 5
Chapter 6
Chapter 7
Chapter 8
Chapter 9
Chapter 10
Chapter 11
Chapter 12
Other Books You May Enjoy
Leave a review - let other readers know what you think
Functional programming languages, such as Java, Scala, and Clojure, are attracting attention as an efficient way to handle the new requirements for programming multi-processor and high-availability applications. This book will teach you functional programming with the help of Scala. The book takes a thought-leadership approach, gently introducing you to functional programming and taking you all the way to becoming a master at the paradigm. Beginning with an introduction to functional programming, the book gradually moves forward teaching you how to write declarative code, making use of functional types and values. After covering the basics, we will discuss the more advanced concepts in functional programming.
We will cover the concepts of pure functions and type classes, problems they aim to solve, and how to use them in practice. We will see how libraries can be used for purely functional programming. We will look at the broad family of libraries for functional programming. Finally, we will discuss some of the more advanced patterns in the functional programming world, such as Monad Transformers and Tagless Final. After covering the purely functional approach to programming, we will look into the subject of parallel programming. We will introduce the Actor model and how it is implemented in the modern functional languages. By the end of this book, you will have mastered the concepts entailing functional programming alongside OOP to build robust applications.
If you are from an imperative and OOP background, this book will guide you through the world of functional programming, irrespective of which programming language you use.
Chapter 1, The Declarative Programming Style, covers the main idea of declarative style of abstracting away repeating algorithmic patterns and control flows so that, with one statement, it is possible to describe what otherwise would have been 10 lines of imperative code. Functional languages usually have an elaborate infrastructure to make such an approach especially relevant and usable. One good way to feel this difference is to have a look at the difference in programming with Java and Scala collections—the former employs the imperative style and latter the functional style.
Chapter 2,Functions and Lambdas, will start with the concept familiar to an OOP programmer—a method. We will then explore some more advanced, functional concepts specific to functional programming—things such as lambdas, currying, generic type parameters, implicit arguments, and higher-order functions. We will see how higher-order functions may be useful to abstract control flow. Finally, we will look at the concept of partial functions.
Chapter 3, Functional Data Structures, explains a functional collections framework. It features a hierarchy of collections data types designed for different scenarios. It then moves to other data types that are not part of the collections framework but are often used in functional programming and hence deserve our attention. The data types are Option, Either, and Try. Finally, we will see how the data structures are separated from their behavior via an implicit mechanism, which is present in some advanced languages.
Chapter 4, The Problem of Side Effects, is about side effects that are ubiquitous in programming. Functional programming advocates for so-called pure functions—functions that do not produce any side effects, which means you can't write a file from such a function, or contact the network. Why would functional programming advocate against functions that cause side effects? Is it possible to write a useful program using pure functions only? This chapter explores these questions.
Chapter 5, Effect Types - Abstracting Away Side Effects, provides solutions to the problems of working with side effects in a pure way. The solution presented by purely functional programming is to turn the side effects you encounter into functional data structures. We will explore the process of identifying side effects and turning them into such data structures. Then, we will quickly realize functions that produce side effects usually work one with another. We will hence explore how one can combine these functions using the concept of the Monad.
Chapter 6, Effect Types in Practice, focuses on the material of the Chapter 3, Functional Data Structures, from a new perspective. We will see how functional data structures have a deeper meaning to the data types-that of representing phenomena as data. A phenomenon is something that happens, such as an exception or a delay. By representing it in data we are able to shield ourselves from the effects of the phenomenon while preserving the information about it.
Chapter 7, The Idea of the Type Classes, explore how the Type Class pattern logically emerges from practical needs encountered when working with effect types.
Chapter 8, Basic Type Classes and Their Usage, outlines the most frequently encountered type classes and their family in general. After discussing the motivation for the creation of type class systems, we proceed further to examine their structure and a few basic type classes from them. Type classes such as Monad and Applicative are frequently used in functional programming, so they deserve some special attention.
Chapter 9, Libraries for Pure Functional Programming, discusses how to use the purely functional techniques (effect types and type classes) learned so far in order to develop server-side software. We will learn how to write concurrent, asynchronous software for responding to HTTP requests, contacting the database. We will also learn about the concurrency model modern functional programming offers.
Chapter 10, Patterns of Advanced Functional Programming, explores how to combine effect types to get new effect types. You will see how to leverage the power of the compiler's type system to check guarantees about the program on compile time.
Chapter 11, Introduction to the Actor Model, starts with examining the traditional model of concurrent programming in details. This model rises a bunch of problems such as race conditions and deadlocks, which make programming in it prone to errors that are particularly hard to debug. This chapter presents the idea of an Actor model that aims to solve these problems.
Chapter 12, The Actor Model in Practice, covers the fundamentals of the framework and its concepts. You will proceed to learn some of the patterns that emerge during actor-oriented programming and also see how Actors interoperate with other widespread concurrency primitives—Futures.
Chapter 13, Use Case - A Parallel Web Crawler, examines a larger concurrent application written with the Actor model. One good such example is a web crawler application. A web crawler is an application that collects links from websites. Starting from a given website, it collects all the links on it, follows them, and recursively collects all the links from them. This chapter will examine how to implement such a larger application.
Appendix A, Introduction to Scala, isa short introduction to the Scala language, which is used for examples throughout the book.
Before reading this book, readers need to know about the concepts of object-oriented and imperative programming.
To test the code of this book, you need Docker version 18.06 or higher and Git version 2.18.0 or higher.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub athttps://github.com/PacktPublishing/Mastering-Functional-Programming. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/MasteringFunctionalProgramming_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "The instances package contains the implementations of the type classes for basic data types that are present in the language core and the ones defined by the Cats library."
A block of code is set as follows:
public void drink() { System.out.println("You have drunk a can of soda.");}
Any command-line input or output is written as follows:
:help
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "The for comprehension is shorthand for sequentially calling flatMap. This technique is called the Monadic flow."
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
Declarative programming is tightly connected to functional programming. Modern functional languages prefer to express programs as algebra and not as algorithms. This means that programs in functional languages are combinations of certain primitives with operators. The technique where you express your programs by specifying what to do, but not how to do it, is referred to as declarative programming. We will explore why declarative programming appeared and where it can be used.
In this chapter, we will cover the following topics:
Principles of declarative programming
Declarative versus imperative collections
Declarative programming in other languages
To run the examples in this book, you will need the following software, as well as basic understanding of how to use it:
Docker version 18.06 or higher:
https://www.docker.com/
Git version 2.18.0 or higher:
https://git-scm.com/
To run the samples:
Clone the
https://github.com/PacktPublishing/Mastering-Functional-Programming
repository on your machine.
From its root, compose and run the Docker set of images specified in
docker-compose.yml
. If you are on a Linux/Mac machine, you can run
./compose.sh
to complete this step. If you are on Windows, open
compose.sh
in text editor and run each command from your terminal manually.
Run shell (Bash) on the Docker service called
mastering-functional-programming
_backend_1
. You can complete this step by running
./start.sh
on a Linux/Mac machine from a separate terminal window. If you are on a Windows machine, run
docker exec -ti mastering_backend bash
. Then
cd Chapter1
for Chapter 1 examples, or
cd ChapterN
for Chapter N examples.
The
cpp
folder contains C++ sources. You can run them with
./run.sh <name-of-the-source>
from that directory.
The
jvm
f
older contains Java and Scala sources. You can run them by running
sbt run
from that directory.
Note that it is necessary to run the examples under Docker. Some chapters run examples against a live database, which is managed by Docker, so make sure to get the above procedure working.
The codes presented in this book are available at: https://github.com/PacktPublishing/Mastering-Functional-Programming
Why declarative programming? How did it appear? To understand declarative programming, we need to first understand how it is different from imperative programming. For a long time, imperative programming has been a de facto industry standard. What motivated people to start switching to the functional style from the imperative style?
In imperative programming, you rely on a set of primitives that your language provides. You combine them in a certain way so as to achieve a functionality that you need. We can understand different things under primitives. For example, these can be loop control structures, or, in the case of collections, operations specific to collections, such as creating a collection and adding or removing elements from a collection.
In declarative programming, you also rely on primitives. You use them to express your program. Yet, in declarative programming, these primitives are much closer to your domain. They can be so close to your domain that the language itself can be regarded as a domain-specific language (DSL). With declarative programming, you are able to create primitives as you go.
In imperative programming, you usually don't create new primitives, but rely on the ones the language provides you with. Let's go through some examples to understand the importance of declarative programming.
Another great illustration of how the declarative style works can be seen in collection frameworks. Let's compare the collection frameworks of an imperative and functional programming language, for example, Java (imperative) collections and Scala (functional) collections.
Why a collection framework? Collections are ubiquitous in any programming project. When you are dealing with a database-powered application, you are using collections. When you are writing a web crawler, you are using collections. In fact, when you are dealing with simple strings of text, you are using collections. Most modern programming languages provide you with the implementation of collection frameworks as part of their core library. That is because you will need them for almost any project.
We'll go into more depth about how imperative collections are different from declarative collections in the next chapter. However, for the purpose of an overview, let's briefly discuss one of the major differences between the imperative and declarative approaches to collections here. We can see such a difference using the example of filtering. Filtering is an ubiquitous operation that you most likely will find yourself doing pretty often, so let's see how it differs across the two approaches.
In other modern languages, such as Haskell or Python, a similar declarative functionality is also present out of the box. For example, you can perform filtering in Python—it is built into the language, and you have a special function in Haskell to perform the same filtering. Also, the functional nature of Python and Haskell makes it easy to implement the same control structure as filtering by yourself. Both Haskell and Python support the notion of the lambda function and higher-order functions, so they can be used to implement declarative control structures.
In general, you can spot whether a language is declarative programming-friendly by looking at the capabilities it provides. Some of the features you can look for are anonymous functions, functions as first-class citizens, and custom operator specifications.
Anonymous lambda gives you a great advantage because you can pass functions to other functions inline, without first defining them. This is particularly useful when specifying control structures. A function expressed in this way is, first and foremost, to specify a transformation that is supposed to transform an input into an output.
Another feature that you can look for in programming languages is support for functions as first-class citizens. This means that you are able to assign a function to a variable, refer to the function by that variable's name, and pass that variable to other functions. Treating functions as if they are ordinary variables allows you to achieve a new level of abstraction. This is because functions are transformations; they map their input values to some output values. And, if the language does not allow you to pass transformations to other transformations, this is a limitation of flexibility.
Another feature that you can expect from declarative languages is that they allow you to create custom operators; for example, the synthetic sugar available in Scala allows you to define new operators very easily, as methods in classes.
The declarative style is a style of programming where you call the operations you want to perform by name, instead of describing how to execute them in an algorithmic fashion via lower-level primitives provided by the programming language. This naturally aligns with the DRY principle. If you have a repeating operation, you want to abstract it away, and then refer to it by name later on. In other words, you need to declare that the operation has a certain name. And, whenever you want to use it, you need to declare your intent, without specifying directly how it should be fulfilled.
Modern functional programming goes hand in hand with the declarative style. Functional programming provides you with a better level of abstraction, which can be used to abstract away the repeating operations.
In the next chapter, we will see how first-class citizen support for functions can be useful for the declarative programming style.
What is the principle behind declarative programming?
What does DRY stand for?
Why is using
go-to
bad style?
The paradigm of functional programming has a lot of common features with the paradigm of declarative programming. One of the defining features of functional languages and declarative programming is the extensive use of functions. This chapter will discuss in more detail what functions are and their meaning in different paradigms. We will have a look at how we can use functions and what their role is in modern programming languages.
In this chapter, we will cover the following topics:
Functions as behaviors
Functions in functional programming
Higher-order functions
Lambdas
The concept of functions in different programming languages
So what are functions? We can define them as parameterized, named chunks of code. This means that they are chunks of code that can be called from any other part of the program by their name. Parameterized means that you can call them with certain arguments. Different calls executed with different parameters usually lead to different results.
What is the motivation behind functions? The answer is the basic principle of engineering – abstract away that which repeats itself. In Chapter 1, The Declarative Programming Style, we saw something similar in the case of loops. However, loops are built-in control structures. This means they are defined at the language level. When we need to define some logic on the language-user level, and this logic repeats itself across different parts of the project, functions come into play.
We can trace functions across paradigms to as early as procedural programming. In procedural programming, functions are one of the units of abstraction. This means that functions encapsulate the logic that repeats. In object-oriented programming, we have an evolution of the understanding of functions. Functions are usually viewed in the context of an object or a class. In this context, they play the role of the behavior of an object.
For example, if you have an object called a soda machine, this object may have certain behaviors associated with it, such as inserting a coin into the machine, or pressing the button to get a can of soda from the machine.
Functions are present in many programming languages. Some of the languages have better support for purely functional styles, while others favor declarative styles. This is why, for example, using Scala over Java can give you tremendous leverage, because you can declare functions inside other functions, you can declare functions that accept other functions (higher-order functions) more easily, and you can declare anonymous lambda functions (functionality also available in Java, starting from Java 8). This greatly increases your capacity for abstraction, creating control structures, and thereby enabling your application to be expressed in a more DRY (Don't Repeat Yourself) way.
In this chapter, we have seen what functions are and how they have evolved from the early days of programming to today. We have seen how functions were initially treated as abstractions of common logic. After that, in object-oriented programming, they represented the behavior of certain objects. Object-oriented programmers attempted to represent everything as an object. So it is only natural that functions started to be viewed in the context of a world that consists of objects. In this context, functions are best viewed as behaviors of these objects.
In functional programming, functions can be viewed in a different context. Now, the best way to view functions is as mathematical computations. They compute some value out of its inputs, in a pure way, which means without any side effects. The idea is to view them as mathematical functions.
Functional programming is close to declarative programming, so its functions are also often tailored to the needs of that style. This way, in functional languages, there is a concept of higher-order functions, anonymous lambda functions, and partial functions. From an engineering perspective, this is useful because it greatly enhances your capability for abstraction.
In programming, data structures are ubiquitous. When adopting functional style, sooner or later you will encounter a problem of working with data structures in a functional way. In the next chapter, we will see how this problem is addressed.
How are functions interpreted in the context of object-oriented programming?
How are functions interpreted in the context of pure functional programming?
What are higher-order functions?
Why are higher-order functions useful?
Programming largely deals with data manipulation. Different styles of programming will treat data structures, and data itself, differently. For example, imperative programming treats data as mutable information stored in memory. We will see how the treatment of functional programming differs from that of imperative programming.
In this chapter, we will cover the following topics:
Collections framework
The algebraic approach
Effect types
Data structures in different programming languages
When discussing data structures, it is only natural to start with collections. Collections are data structures that abstract away multiplicity. This means that whenever you have more than one item of a particular kind, and you want to run a number of operations on this data, you will need a proper abstraction—an abstraction that will establish the rules of the game you play when you encounter multiplicity.
It transpires that you will need to deal with abstraction of this nature in nearly every programming project. When you are dealing with strings, you frequently need to represent them as a collection of characters. Whenever you have a database application, and you have some queries in relation to this database, you need to present multiple results of these queries as collections. Whenever you are dealing with a text file, you may want to represent it as a list of lines. This happens rather frequently, for example, when dealing with configuration files. We specify our configuration entries as strings on separate lines. For example, the following is how we may represent a server connection configuration:
host=192.168.12.3port=8888username=rootpassword=qwerty
Or, for example, you may want to communicate data with a web API. Most modern web APIs communicate data in the form of JSON or XML. These are structured ways of representing data and, if you observe them closely, you will notice that they follow a pattern; for example, an XML file is composed of a tree of multiple nodes, and a JSON object may contain more than one entry.
So, whenever you are working on a programming project, it is very likely that you will need to deal with some kind of abstraction over multiplicity. You require a collections framework. Because collections are so ubiquitous, it is only natural that modern programming languages include a collection framework in their core library. This is why looking at a language's collections framework is an easy way to see the philosophy of the language and its approach to programming in general.
In this section, we will compare the collection frameworks of Java and Scala. Java represents a traditional, imperative approach to programming, and, hence, its collection framework also reflects this approach. On the other hand, Scala represents a functional, declarative approach to programming. Its collection framework is built and structured according to the philosophy of functional and declarative programming.
