Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
F# 4.0 Design Patterns
F# 4.0 Design Patterns

F# 4.0 Design Patterns: Solve complex problems with functional thinking

Arrow left icon
Profile Icon Gene Belitski
Arrow right icon
$19.99 per month
Full star icon Full star icon Full star icon Half star icon Empty star icon 3.5 (4 Ratings)
Paperback Nov 2016 318 pages 1st Edition
eBook
$27.98 $39.99
Paperback
$48.99
Subscription
Free Trial
Renews at $19.99p/m
Arrow left icon
Profile Icon Gene Belitski
Arrow right icon
$19.99 per month
Full star icon Full star icon Full star icon Half star icon Empty star icon 3.5 (4 Ratings)
Paperback Nov 2016 318 pages 1st Edition
eBook
$27.98 $39.99
Paperback
$48.99
Subscription
Free Trial
Renews at $19.99p/m
eBook
$27.98 $39.99
Paperback
$48.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing
Table of content icon View table of contents Preview book icon Preview Book

F# 4.0 Design Patterns

Chapter 1. Begin Thinking Functionally

A man with a chainsaw enters a hardware shop and says to the assistant: "Two weeks ago, you told me this thing would allow me to chop down 30 trees in an hour. But I can only manage one tree. I want to return this for a refund". The assistant says "let me see" and starts the chainsaw. The visitor jumps back screaming "What's that noise?!"-An old joke

The joke opening my narrative is very relevant to the subject of this chapter: in order to achieve the benefits expected from the use of any tool, you should know how to use that tool the right way. Moreover, an advanced tool used in a wrong manner may be even less productive than the corresponding simple one used the right way. A hammer outperforms a microscope when it comes to nailing wooden boards together.

Chapter 1, Begin Thinking Functionally, should help you develop a manner of solving day-to-day software engineering problems that are usually associated with the functional paradigm. This means presenting the solution by verbs rather than nouns, avoiding the use of mutable entities to carry states, avoiding relying upon side-effects, and minimizing the amount of moving parts in the code.

In this chapter, we will cover the following topics:

  • The multi-paradigm nature of F#
  • A comparison of F# paradigms by solving the sample problem applying:
    • An imperative monolithic solution
    • An object-oriented solution
    • A functional solution
  • Properties of the functional paradigm

I will wrap up this chapter with a list of key concepts to retain and recognize, as well as skills to reuse in your functional solutions.

Relationship between F# and programming paradigms

This chapter, as well as the other chapters, will teach you how to look at any given software problem from the functional paradigm angle. This view may differ significantly from paradigmatic views that you may have already developed while practising other programming approches. This assumption of the required paradigmatic shift is a much anticipated scenario, taking into consideration the factor of the programming language popularity of the so called TIOBEProgramming Community index (http://www.tiobe.com/tiobe_index?page=index), which can be considered an indicator of the popularity of programming languages.

At the time of this writing (February 2016):

  • The winning Rank #1 of TIOBE index is held by the Java programming language, which is strongly associated with the object-oriented programming paradigm
  • Rank #2 belongs to the C programming language, which can be considered representing as the traditional imperative procedural programming paradigm
  • Programming languages associated with the functional programming paradigm make it into the TIOBE index ranks only for the rank range of 21 to 50, where F# carries modest Rank #36

Nevertheless, if you've managed to read upto this point, I can safely assume that your interest in F# is not driven by its mere popularity, which, in turn, is driven by factors that do not belong to the scope of this book. For me, the bearer of an advanced degree in applied math and computer science, engineering program code within the F# ecosystem carries these intangible aesthetic qualities similar to ones of exploring a beautiful solution of a math problem or from analyzing a great chess play.

Talking seriously, I personally value most of the functional paradigm benefits of the functional code readability and maintainability. The same qualities of a typical monolithic imperative C code might be quite poor. However, are these code qualities automatically granted for anyone who has grasped mere F# syntax? Certainly not.

In addition to learning the F# syntax, the preceding point means acquiring certain skills in order to use this programming language in an idiomatic manner. F# is a multi-paradigm programming language indeed. It allows programmers to entertain many programming paradigms. The functional manner of laying out the program code can be used side by side with the imperative monolithic programming manner, or an object-oriented approach may surface when interoperability with the environment is important . Nevertheless, F# makes a claim of being a functional-first programming language. This means that the congenial programming paradigm for F# is the functional one; the language will bring to the table most benefits if it's used in a functional manner, in which case:

"it empowers users and organizations to tackle complex computing problems with simple, maintainable and robust code"-(http://fsharp.org/).

You may wonder what, exactly, idiomatic usage means and whether it will be possible to always use it. The best way of illustrating idiomatic F# use would be by performing a comparative study of correspondent coding examples. Let me take an arbitrary, simple problem and solve it by sticking to imperative, then to object-oriented, and finally, to functional paradigms. Then, I am going to compare solutions to highlight functional approach features. In order to make this comparison absolutely fair, the programming language of implementation in all three cases is going to be F#.

A sample problem to solve

I will use as a problem for the purpose the slightly amended version of Problem 8 of Project Euler (https://projecteuler.net/problem=8):

The four adjacent digits (9989) being highlighted in the 1000-digit numbers that have the greatest product are as following: 
9 x 9 x 8 x 9 = 5832. 
 
73167176531330624919225119674426574742355349194934 
96983520312774506326239578318016984801869478851843 
85861560789112949495459501737958331952853208805511 
12540698747158523863050715693290963295227443043557 
66896648950445244523161731856403098711121722383113 
62229893423380308135336276614282806444486645238749 
30358907296290491560440772390713810515859307960866 
70172427121883998797908792274921901699720888093776 
65727333001053367881220235421809751254540594752243 
52584907711670556013604839586446706324415722155397 
53697817977846174064955149290862569321978468622482 
83972241375657056057490261407972968652414535100474 
82166370484403199890008895243450658541227588666881 
16427171479924442928230863465674813919123162824586 
17866458359124566529476545682848912883142607690042 
24219022671055626321111109370544217506941658960408 
07198403850962455444362981230987879927244284909188 
84580156166097919133875499200524063689912560717606 
05886116467109405077541002256983155200055935729725 
71636269561882670428252483600823257530420752963450 
 
Find the five adjacent digits in the same 1000-digit number that has the greatest product. What is the value of this product? 

An imperative monolithic solution

Let me begin by approaching the solution in a straightforward monolithic imperative manner: convert the 1000-character string representing the number into a character array, and then convert it into a cycle across all 996 groups of the five adjacent digits, calculating the digit product of each group and maintaining the current maximum. The final value of the current maximum will be the solution; it's that simple.

In order to remove the input number from the way, let's put it into a separate source code file, HugeNumber.fs, pulled to the solution scripts with the F# #load directive. The F# source file HugeNumber.fs is shown as follows:

[<AutoOpen>] 
module HugeNumber 
let hugeNumber = 
    "73167176531330624919225119674426574742355349194934\ 
    96983520312774506326239578318016984801869478851843\ 
    85861560789112949495459501737958331952853208805511\ 
    12540698747158523863050715693290963295227443043557\ 
    66896648950445244523161731856403098711121722383113\ 
    62229893423380308135336276614282806444486645238749\ 
    30358907296290491560440772390713810515859307960866\ 
    70172427121883998797908792274921901699720888093776\ 
    65727333001053367881220235421809751254540594752243\ 
    52584907711670556013604839586446706324415722155397\ 
    53697817977846174064955149290862569321978468622482\ 
    83972241375657056057490261407972968652414535100474\ 
    82166370484403199890008895243450658541227588666881\ 
    16427171479924442928230863465674813919123162824586\ 
    17866458359124566529476545682848912883142607690042\ 
    24219022671055626321111109370544217506941658960408\ 
    07198403850962455444362981230987879927244284909188\ 
    84580156166097919133875499200524063689912560717606\ 
    05886116467109405077541002256983155200055935729725\ 
 71636269561882670428252483600823257530420752963450" 

This file is going to be used by all variants of the problem solutions.

Then, F# script Ch1_1.fsx implementing an imperative solution will look as follows:

// Imperative monolithic solution a-la C/C++ 
#load "HugeNumber.fs" 
let number = hugeNumber.ToCharArray() 
let mutable maxProduct = 0 
let charZero = int('0') 
for i in 0..995 do 
  let mutable currentProduct = 1 
for j in 0..4 do 
  currentProduct <- currentProduct * (int(number.[i + j]) -      charZero) 
if maxProduct < currentProduct then 
  maxProduct <- currentProduct 
printfn "%s %d" "Imperative solution:" maxProduct 

The line #load "HugeNumber.fs" brings a string value HugeNumber.hugeNumber from the external code file HugeNumber.fs into the scope of this script.

The next line, let number = hugeNumber.ToCharArray() converts this string value into an array of 1000 individual characters, each representing a single digit.

The next line, let mutable maxProduct = 0 introduces a mutable int value used to carry the running tally of a maximal product of five adjacent digits.

The following line let charZero = int('0') is just a helper value used for converting a character code of a digit into an actual int value in the range of 0 to 9. It represents integer 48 indeed, not 0 as some of you may expect. But given char values of decimal digits '0' to '9' all have adjacent values after being converted to int, the simple subtraction of charZero from the result of converting a char digit x into an int will yield exactly x as an integer. More details on this matter will be given as we proceed further in this chapter.

The following seven lines of F# code are the gist of implementation:

for i in 0..995 do 
  let mutable currentProduct = 1 
for j in 0..4 do 
  currentProduct <- currentProduct * (int(number.[i + j]) -     charZero) 
if maxProduct < currentProduct then 
  maxProduct <- currentProduct 

This part of the script performs the following actions:

  • The outer numerical for loop traverses the number array from the leftmost to the rightmost chunk of the five adjacent character digits, keeping the sequential number of the chunk (0,1,2,...,955) in the counter value i.
  • The binding let mutable currentProduct = 1 provides a mutable placeholder for the product of the current chunk's digits.
  • The inner numerical for loop traverses a subarray of length 5, calculating currentProduct by multiplying the intermediary result by the int value of each digit having sequential number j using the expression (int(number.[i + j]) - charZero). For example, if a current digit is 5, then int('5') - int('0') = 5.
  • An if statement closing the outer loop ensures that maxProduct always contains the maximal product of already traversed chunks; hence, when the loop completes iterating, maxProduct contains the sought value.

Finally, the line printfn "%s %d" "Imperative solution:" maxProduct outputs the final result to the system console.

Running the script in its entirety with F# Interactive (FSI) yields the following solution:

An imperative monolithic solution

Running an imperative solution script in F# Interactive

There are a few points that I would like to accentuate prior to covering other approaches to solving the problem as follows:

  • The solution represents detailed "how-to" instructions
  • The solution has been expressed in terms of low-level computer notions, such as statements, loops, and global values
  • Values change along the execution, representing the changing state
  • The solution code does not look structured, it just flows

An object-oriented solution

Now let me turn to the object-oriented manner of solving the same problem. It is typical for this kind of approach to hide implementation details inside instances of custom classes and manipulate them with the help of their own methods. I will use for this purpose the F# type feature representing the concept of the .NET object type also known as class (https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/classes). An object-oriented solution to the problem is present in the following code (script Ch1_2.fsx):

// Object-oriented solution a-la C# with Iterator pattern 
#load "HugeNumber.fs" 
 
open System 
open System.Collections.Generic 
 
type OfDigits(digits: char[]) = 
    let mutable product = 1 
    do 
        if digits.Length > 9 then // (9 ** 10) > Int32.MaxValue 
            raise <| ArgumentOutOfRangeException 
              ("Constrained to max 9 digit numbers") 
        let charZero = int '0' in 
        for d in digits do 
            product <- product * ((int d) - charZero) 
        member this.Product 
            with get() = product 
 
type SequenceOfDigits(digits: string, itemLen: int) = 
    let collection: OfDigits[] = 
       Array.zeroCreate(digits.Length -itemLen + 1) 
    do 
      for i in 0 .. digits.Length - itemLen do 
        collection.[i] <- OfDigits(digits.[i..
           (i+itemLen-1)].ToCharArray()) 
    member this.GetEnumerator() = 
        (collection :> IEnumerable<OfDigits>).GetEnumerator() 
 
let mutable maxProduct = 1 
for item in SequenceOfDigits(hugeNumber,5) do 
    maxProduct <- max maxProduct item.Product 
 
printfn "%s %d" "Object-oriented solution:" maxProduct 

This solution is going to manipulate the objects of two classes. The first class named OfDigits represents the entity of the digit sequence, the product of which is the subject of our interest. An instance of OfDigits can be created from an array of a certain size of char elements carrying digits used as an argument to the OfDigits type constructor OfDigits(digits: char[]).

Upon its creation, each instance is associated with the product field representing the product of its digits. There is a reason for it not being possible to initialize product at once: in order to be representable as a positive integer value, the product can be constituted of nine digits or fewer (because the product of 10 or more 9 would exceed the maximum 32-bit int value 2147483647). In order to validate this, product is kept mutable and initially gets a value of 1 as given in the following line:

let mutable product = 1 

Then, after the length validity check, the OfDigits constructor provides the genuine value to the field by performing the calculation:

let charZero = int '0' in 
for d in digits do 
  product <- product * ((int d) - charZero) 

This value can be accessed via the instance property, Product as shown in the following line:

member this.Product with get() = product 

The another class required to implement the object-oriented solution represents the entity taking a string of digits of arbitrary length and represents it as a generic collection of type OfDigits, allowing enumeration in order to traverse it and find a member with the maximum Product property.

For this purpose, the class named SequenceOfDigits has been equipped with a constructor parameterized by the digits string carrying the input number's digits and the itemLen length of individual OfDigits instance arguments. During the SequenceOfDigits instance construction, all OfDigits instances are created as elements of the collection field array. The GetEnumerator() instance method allows you to enumerate this array by upcasting to the System.Collections.Generic.IEnumerable<OfDigits> interface type and delegating the call to the GetEnumerator() method of the latter in the following instance method definition:

member this.GetEnumerator() =  (collection :> IEnumerable<OfDigits>).GetEnumerator() 

Having the preceding two classes at your disposal makes composing the solution of the original problem rather simple: you construct a SequenceOfDigits instance of five digit OfDigits elements off hugeNumber and traverse it with the help of the for...in cycle, maintaining the maximum product tally similarly to the imperative solution as shown in the following code:

let mutable maxProduct = 1 
for item in SequenceOfDigits(hugeNumber,5)
  do  maxProduct <- max maxProduct item.Product 

In the end, place the result on the system console. Running the script in its entirety with F# FSI yields the result of object-oriented solution as shown in the following screenshot:

An object-oriented solution

Running object-oriented solution script in F# Interactive

For those of you familiar with the object-oriented manner of approaching problem solutions, you may anticipate that the second solution rather differs from the first one:

  • It is distinctively structured, with the segregation of definitions of pertinent classes from the usage of these classes
  • Classes hide details of implementation, allowing usage only through exposed properties and methods
  • The solution follows one of the well-known design patterns, namely the iterator pattern
  • The amount of effort required for scaffolding substantially exceeds the effort required for the solution per se

A functional solution

Finally, let me turn to the solution manner that this book targets, namely, functional. Let's think of it as a series of data transformations. Let's look at it in a backward direction, from the sought solution back to the input string of digits as follows:

  • The sought solution is the result of the max aggregate function application to the sequence of all products of five digit sequences.
  • The sequence of all five digit sequences products is the result of the function application that maps each five digit sequence instance from the sequence of such sequences to the reduce of five digit sequence digits to their product.
  • The sequence of all five digit sequences can be produced from the sequence of all initial digits by applying the F# core library windowing function Seq.windowed<'T> to the latter. In other words, this means taking a copy sequence of the first five digits from the left-hand side, placing this sequence in the output, shifting to the right of the source sequence by one digit, taking the first five digit copy and putting them after the first group in the output, shifting to the right by one digit of the source again, taking the first five digits, and so on, until there is no more possibility of taking the first five digits from the source. The output sequence of sequences is the sought function application result.
  • Finally, the sequence of all initial digits is simply the initial string split by single digits, each converted into correspondent int from 0 to 9.

Each preceding step describes what transformation I want to apply to the single input argument in order to get the single result. Each next step takes the result of the previous step and treats it as its own input.

Let me show you how I usually derive the working code from the data transformation sketch similar to the preceding one with the help of the Read-Evaluate-Print-Loop (REPL) mode provided by FSI and the shrinking task dimension. The process of sequential progress toward the solution is shown in Fig.1.3, where I gradually start adding transformation steps to reproduce the data transformation process sketched earlier for a string consisting of just 10 digits "0918273645" by following these steps:

  1. The input string is piped forward with the F# operator of the same name pipe-forward |> as the second argument of Seq.map string. The result is the sequence of 10 strings, each representing a single digit.
  2. The result of step 1 is piped forward with |> as the second argument of Seq.map int. Now, the result is also the sequence, but it is a sequence of 10 int numbers, each representing the single digit.
  3. The result of step 2 is piped forward with |> as the second argument of Seq.windowed 5. The result is the sequence of six arrays, each representing five sequentially taken digits of the result of step 2, each time shifting the beginning of the sequence to the right by one position.
  4. The result of step 3 is piped forward with |> as the second argument of Seq.map (Seq.reduce (*)). The first argument is the higher-order function Seq.reduce converting its argument, which is an array of five numbers to the product of these numbers with the help of the multiplication operator ( * ). The result of this transformation step is just six numbers, each representing the product of the elements of the corresponding digit array.
  5. The result of step 5 is piped into the Seq.max aggregate function, which produces the sought maximal product that equals 2520(7 * 3 * 6 * 4 * 5)w:

A functional solution

The incremental process of getting to the smaller problem solution with REPL

Now, after becoming pretty confident that the thought-out solution is good, I can combine the preceding steps 1 to 5 with just another F# function composition operator >>, which just glues the result of the function to the left as an argument of the function to the right into a very compact F# script provided in the file Ch1_3.fsx as follows:

#load "HugeNumber.fs" 
hugeNumber |> (Seq.map (string >> int) >> Seq.windowed 5 
>> Seq.map (Seq.reduce (*)) >> Seq.max 
>> printfn "%s %d" "Functional solution:") 

The only difference between the preceding complete problem solution code and the smaller problem solution that I was running through a few REPL steps is the input value dimension. The final code uses the same 1000 digit hugeNumber taken from the source file HugeNumber.fs in the same manner as the imperative and object-oriented solutions did previously.

Running the script in its entirety with FSI yields the functional solution result shown in the following figure:

A functional solution

Running the functional solution script in F# Interactive

The code quality achieved by the functional solution, despite somewhat lengthy accompanying comments, is quite outstanding:

  • It does not utilize even a single value carrying an intermediate state
  • It contains just one arithmetic multiplication operator absolutely needed for product calculation
  • It is extremely succinct
  • It almost literally reflects the original "what to do" considerations
  • It uses solely half a dozen core F# library functions combined in a certain way, and we may strongly believe that the implementations of these functions are error-free and performant

The preceding bullet points reflect pretty much all the properties typical for an idiomatic functional solution of a small-scale problem. Now I'm going to decipher these properties one by one.

Immutability of participating data entities

The positive qualities of the approach of not using mutable program entities are well known:

  • Given the right state upon construction the immutable cannot be invalidated it during its whole lifetime
  • Immutable entities are easy to test
  • They do not require cloning or copy constructors
  • Immutable entities are automatically thread-safe

I must note that F# is not 100% strict about using immutable entities. As you may have already noticed, I used values, changing the state in my imperative and object-oriented solutions earlier. But the language requires the programmer to make an extra effort to introduce a changeable state (with the mutable modifier to let binding or via ref cells, although F# 4.0 pretty much eliminates the need for the latter).

Also, the majority of data structures introduced by the language are also immutable, which means that a typical data transformation produces a new immutable instance of a data structure from the existing data structure. This consideration requires a certain caution from programmers when dealing with bulk in-memory instances, but as my experience has taught me, developers get used to this feature easily.

Thinking in verbs rather than nouns

Considering the process of data transformations in terms of verbs rather than nouns is very typical for a functional approach as functions are intuitively associated in our brains with actions, not objects. You may notice the single data item in the script Ch1_3.fsx, which is hugeNumber. The rest are few library functions combined in a certain manner, which transform the hugeNumber data item into a line of the console output. This manner of function combination allows persons reading this code to completely ignore intermediate results of the data transformations at each point where the operator >> occurs in the expression.

The less obvious corollary of this combination is the opportunity for the F# compiler to perform a so-called fusion or the manner of code optimization by merging together some adjacent data transformation steps. For example, when adjacent steps are fused together, the amount of data traversals may decrease.

"What" prevailing over "how"

This property of the functional solution mental process is easier to demonstrate with an example. I paraphrase here the great one from the early days of F# that's been used by several insiders previously. Imagine yourself in Starbucks for Caffè Americano.

The "how" approach would be to give detailed instructions such as:

  1. Take a roasted coffee
  2. Brew two espresso shots
  3. Top them with hot water to produce a layer of crema
  4. Put it into a cap of 12 oz size

The "what" approach would be to just ask "May I have a tall Caffè Americano?".

The second approach is evidently much more succinct and minimizes an opportunity of getting a result that deviates from the desired one. If you revisit now our three preceding solutions you should spot this property there.

Generalization over specialization

Another outstanding feature of the functional paradigm is generalization. By this, I mean preferring a general solution over a concrete one, when a concrete problem can be solved by applying a general solution that is accordingly parameterized. Let's turn to our sample problem for evidence of generalization. Adjusting the functional solution to a different length of digit sequences (for example, 8 instead of 5), another math operation on the group (for example, the sum instead of the product), another aggregation property (for example, minimum instead of maximum) are mere changes of parameter values for the correspondent functions. A comparison of how much the code changes will be required in case of the other approaches, which I leave for you as an exercise.

Minimizing moving parts over hiding them

This property is specifically related to a functional approach in comparison with an object-oriented one. Recall F# script file Ch1_2.fsx, which involved custom classes encapsulating details of implementation and exposing them outside the constructor, the iterator, and the aggregated property. In comparison with the object-oriented approach, the functional approach is flat and does not hide anything; it just combines some known parts.

Reduction to known parts over producing custom parts

One of the amazing properties of a functional paradigm differentiating it from the others is the limited need for producing custom parts at the level of manipulating data structures. Usually, functional programming newbies tend to implement their own functions for each case of data transformation. This infantile sickness normally ends with finding out from practice that pretty much any transformation upon typical data structures can be expressed as a combination of filter, map, and fold operations. I will devote a substantial amount of contents in relation to this phenomenon.

Lazy over eager data collections

Let me turn your attention to the comparison of memory consumption of the previously mentioned object-oriented and functional solutions. The object-oriented solution eagerly creates, materializes in computer memory the collection of 996 OfDigits objects; that is, its memory consumption is a linear function of the problem dimensions. In contrast to this approach, the functional solution does not require more than a single instance of OfDigits at any moment of the max aggregation, lazily producing the same 996 objects one by one according to the demand of the max aggregator function, hence having memory consumption that is constant and (almost) independent of the problem dimensions. This is a rather complex quality. If you imagine that the initial condition has suddenly changed and hugeNumber is really huge, then the object-oriented solution may become non-applicable due to the lack of required memory, while the functional solution, being agnostic to this factor, will continue to work. Generalizing this observation, the functional paradigm allows you to solve problems of a bigger scale, rather than taking other approaches by utilizing the lazy manner of data manipulation. The interesting corollary stemming from this approach is the technique of manipulating data sequences of unlimited length that do not require their complete materialization in the memory.

Summary

The following are the key concepts and the list of skills you should take away after finishing this chapter and strive for absorbing and mastering:

Avoid mutable state and achieve data transformations over immutable values and data structures. Think of programming solutions in terms of verbs rather than nouns. Avoid expressing a solution in highly detailed imperative "how" statements; use the "what to do" approach instead. Generalize: prefer a general parameterized solution to a concrete one. Strive to minimize the moving parts of your solution instead of hiding these moving parts into classes. Try expressing solutions by a few well-known facilities instead of delving into producing custom ones. When appropriate, prefer lazy data collections (sequences) over eager ones.

This process of mastering the functional manner of thinking may be framed around the following three Rs - Retain, Recognize, and Reuse. The sooner you learn to recognize idiomatic functional design patterns which I'm going to cover with a great amount of detail in this book and the sooner you reuse these patterns again and again in your day-to-day coding activities, the better functional programmer you will become.

In the upcoming chapters, I will walk you over the many idiomatic uses of F# in certain development situations. These repeated usages will represent genuine functional programming design patterns. Please keep in mind that many of these patterns only to a certain extent correlate with traditional object-oriented design patterns (https://en.wikipedia.org/wiki/Design_Patterns), as well as other architecture design patterns of software engineering (http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420).

In the next chapter, I'll give you a 360-degree high-level view of the F# language features and parts with their origins and evolvement.

Left arrow icon Right arrow icon

Key benefits

  • This book provides a path if you are coming from imperative and object-oriented paradigms
  • It will take you to an intermediate level of functional programming in very practical manner to write enterprise-quality idiomatic F# code
  • Tackle complex computing problems with simple code by fully embracing the functional-first F# paradigm
  • Packed full of practical coding examples to help you master F# programming and author optimal code

Description

Following design patterns is a well-known approach to writing better programs that captures and reuses high-level abstractions that are common in many applications. This book will encourage you to develop an idiomatic F# coding skillset by fully embracing the functional-first F# paradigm. It will also help you harness this powerful instrument to write succinct, bug-free, and cross-platform code. F# 4.0 Design Patterns will start off by helping you develop a functional way of thinking. We will show you how beneficial the functional-first paradigm is and how to use it to get the optimum results. The book will help you acquire the practical knowledge of the main functional design patterns, the relationship of which with the traditional Gang of Four set is not straightforward. We will take you through pattern matching, immutable data types, and sequences in F#. We will also uncover advanced functional patterns, look at polymorphic functions, typical data crunching techniques, adjusting code through augmentation, and generalization. Lastly, we will take a look at the advanced techniques to equip you with everything you need to write flawless code.

Who is this book for?

This book is for .NET developers, web programmers, C# developers, and F# developers. So, if you have basic experience in F# programming and developing performance-critical applications, then this book is for you.

What you will learn

  • Acquire the practical knowledge to use the main functional design patterns
  • Realign some imperative and object-oriented principles under the functional approach
  • Develop your confidence in building and combining first-order and higher-order functions
  • Learn to use core language pattern matching effectively
  • Make use of native F# algebraic data types in place of custom-built classes
  • Recognize and measure the difference in resource consumption between sequences and materialized data collections
  • Navigate and use F# Core libraries with ease by seeing patterns behind specific library functions
  • Master writing generic polymorphic code

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Nov 30, 2016
Length: 318 pages
Edition : 1st
Language : English
ISBN-13 : 9781785884726
Category :
Languages :

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing

Product Details

Publication date : Nov 30, 2016
Length: 318 pages
Edition : 1st
Language : English
ISBN-13 : 9781785884726
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 146.97
Mastering F#
$48.99
F# 4.0 Design Patterns
$48.99
F# High Performance
$48.99
Total $ 146.97 Stars icon

Table of Contents

13 Chapters
1. Begin Thinking Functionally Chevron down icon Chevron up icon
2. Dissecting F# Origins and Design Chevron down icon Chevron up icon
3. Basic Functions Chevron down icon Chevron up icon
4. Basic Pattern Matching Chevron down icon Chevron up icon
5. Algebraic Data Types Chevron down icon Chevron up icon
6. Sequences - The Core of Data Processing Patterns Chevron down icon Chevron up icon
7. Advanced Techniques: Functions Revisited Chevron down icon Chevron up icon
8. Data Crunching – Data Transformation Patterns Chevron down icon Chevron up icon
9. More Data Crunching Chevron down icon Chevron up icon
10. Type Augmentation and Generic Computations Chevron down icon Chevron up icon
11. F# Expert Techniques Chevron down icon Chevron up icon
12. F# and OOP Principles/Design Patterns Chevron down icon Chevron up icon
13. Troubleshooting Functional Code Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Half star icon Empty star icon 3.5
(4 Ratings)
5 star 50%
4 star 0%
3 star 0%
2 star 50%
1 star 0%
Fernando Saldanha Feb 16, 2017
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Great book. Delivers what it promises. Not for beginners.F# allows the programmer to write standard OO programs. The reader of this book will get a better understanding of F# (an functional programming languages in general), which will facilitate transitioning to a programming style that fully exploits the capabilities of the F# language. The language features are neatly classified and the role of each category is explained.Chapter 12 also contains an excellent discussion of the SOLID principles of OO programming and their counterparts (or lack thereof, not for lack of implementation, but for lack of need) in FP.
Amazon Verified review Amazon
Richard Broida Dec 28, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
There are a lot of good F# books, but this is a great one to start with because it explains the concepts along with the syntax. You need the concepts both to use the language and to explain to your fellow programmers why they should use the language. There's a chapter on GOF-style patterns, but the book's scope is much more comprehensive that that.
Amazon Verified review Amazon
Hugh W. Gleaves Aug 14, 2017
Full star icon Full star icon Empty star icon Empty star icon Empty star icon 2
I had high expectations for this book, being someone fairly new to F# and the functional discipline.Sadly it disappointed me as offering nothing beyond what most other F# books cover. There was too much emphasis on imperative programming, no significant coverage of computation expressions, it was also pretty obvious that the author knew his subject bud had written in poorly in English, a greater editorial presence here would have helped. Frankly it was money wasted since there was nothing in the book that isn't easily found elsewhere.
Amazon Verified review Amazon
Talmage Mar 24, 2017
Full star icon Full star icon Empty star icon Empty star icon Empty star icon 2
Overall, the explanation of functional programming paradigms and techniques is solid. The biggest obstacle to adopting F# is not syntax or functions--which are the focuses of many books--but rather understanding how to think in new terms as a functional programmer. This book does a good job of teaching these techniques.My problem is that the proofreading is atrocious. First, the narrative sections have many grammatical issues and incorrect words (e.g. "seize" instead of "cease") which interrupt flow. Additionally, the spacing in the Kindle cloud version is often off, which can be a big problem in a language like F# in which whitespace matters.More glaring, however, is that the source code is incomplete. For example, in Chapter 6, the text states "Additional information for those of you who are eager to dig deeper is given in the Ch6_1.fsx script of this book's accompanying code, where the use of each of the library functions is illustrated by a brief code sample." In the first four sections (aggregation, generation, wrapping/type conversion, and appliers patterns), only a couple of functions are not illustrated. However for the final three sections (recombination, filter, and mapper patterns), NONE of the illustrations are present. NOT A SINGLE ONE of the 38 or so functions listed. Additionally, I wonder how complete and updated the list even is, considering the deprecated "Seq.nth" function is provided instead of the newer "Seq.item".In short, this book could have been really good, but it seems rushed and sloppy. If there were a good errata, I could make do. However, it is surprising to find that no errata yet exist on the book web page (at packthub.com). I'm considering returning the Kindle purchase for a refund. Hopefully a more polished version will emerge later.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is included in a Packt subscription? Chevron down icon Chevron up icon

A subscription provides you with full access to view all Packt and licnesed content online, this includes exclusive access to Early Access titles. Depending on the tier chosen you can also earn credits and discounts to use for owning content

How can I cancel my subscription? Chevron down icon Chevron up icon

To cancel your subscription with us simply go to the account page - found in the top right of the page or at https://subscription.packtpub.com/my-account/subscription - From here you will see the ‘cancel subscription’ button in the grey box with your subscription information in.

What are credits? Chevron down icon Chevron up icon

Credits can be earned from reading 40 section of any title within the payment cycle - a month starting from the day of subscription payment. You also earn a Credit every month if you subscribe to our annual or 18 month plans. Credits can be used to buy books DRM free, the same way that you would pay for a book. Your credits can be found in the subscription homepage - subscription.packtpub.com - clicking on ‘the my’ library dropdown and selecting ‘credits’.

What happens if an Early Access Course is cancelled? Chevron down icon Chevron up icon

Projects are rarely cancelled, but sometimes it's unavoidable. If an Early Access course is cancelled or excessively delayed, you can exchange your purchase for another course. For further details, please contact us here.

Where can I send feedback about an Early Access title? Chevron down icon Chevron up icon

If you have any feedback about the product you're reading, or Early Access in general, then please fill out a contact form here and we'll make sure the feedback gets to the right team. 

Can I download the code files for Early Access titles? Chevron down icon Chevron up icon

We try to ensure that all books in Early Access have code available to use, download, and fork on GitHub. This helps us be more agile in the development of the book, and helps keep the often changing code base of new versions and new technologies as up to date as possible. Unfortunately, however, there will be rare cases when it is not possible for us to have downloadable code samples available until publication.

When we publish the book, the code files will also be available to download from the Packt website.

How accurate is the publication date? Chevron down icon Chevron up icon

The publication date is as accurate as we can be at any point in the project. Unfortunately, delays can happen. Often those delays are out of our control, such as changes to the technology code base or delays in the tech release. We do our best to give you an accurate estimate of the publication date at any given time, and as more chapters are delivered, the more accurate the delivery date will become.

How will I know when new chapters are ready? Chevron down icon Chevron up icon

We'll let you know every time there has been an update to a course that you've bought in Early Access. You'll get an email to let you know there has been a new chapter, or a change to a previous chapter. The new chapters are automatically added to your account, so you can also check back there any time you're ready and download or read them online.

I am a Packt subscriber, do I get Early Access? Chevron down icon Chevron up icon

Yes, all Early Access content is fully available through your subscription. You will need to have a paid for or active trial subscription in order to access all titles.

How is Early Access delivered? Chevron down icon Chevron up icon

Early Access is currently only available as a PDF or through our online reader. As we make changes or add new chapters, the files in your Packt account will be updated so you can download them again or view them online immediately.

How do I buy Early Access content? Chevron down icon Chevron up icon

Early Access is a way of us getting our content to you quicker, but the method of buying the Early Access course is still the same. Just find the course you want to buy, go through the check-out steps, and you’ll get a confirmation email from us with information and a link to the relevant Early Access courses.

What is Early Access? Chevron down icon Chevron up icon

Keeping up to date with the latest technology is difficult; new versions, new frameworks, new techniques. This feature gives you a head-start to our content, as it's being created. With Early Access you'll receive each chapter as it's written, and get regular updates throughout the product's development, as well as the final course as soon as it's ready.We created Early Access as a means of giving you the information you need, as soon as it's available. As we go through the process of developing a course, 99% of it can be ready but we can't publish until that last 1% falls in to place. Early Access helps to unlock the potential of our content early, to help you start your learning when you need it most. You not only get access to every chapter as it's delivered, edited, and updated, but you'll also get the finalized, DRM-free product to download in any format you want when it's published. As a member of Packt, you'll also be eligible for our exclusive offers, including a free course every day, and discounts on new and popular titles.