F# Pattern Matching

F# Pattern Matching allows you to match the structure of data with patterns and execute code based on the match. In this article, we will explore F# pattern matching in detail and learn how to use it effectively.



What is F# Pattern Matching?

F# Pattern matching is a language construct that allows you to match patterns in data structures and perform operations based on the match. It is a powerful feature that makes code more concise and expressive. F# has a sophisticated pattern matching system that provides a wide range of pattern matching capabilities.

The pattern matching feature of F# is one of the most powerful techniques available for decomposing and extracting information from complex data structures, including lists, records, discriminated unions, as well as their functional relationships, in a concise and expressive manner.


How to Use F# Pattern Matching?

In F#, pattern matching is achieved using the match expression. The match expression takes a value and matches it against one or more patterns. If the value matches one of the patterns, the corresponding action is executed. If the value does not match any of the patterns, an exception is thrown.

Thus, it is one of the most convenient and powerful ways to test data against a number of different criteria, which makes it more efficient and flexible. Furthermore, it is also capable of performing some calculations that are based on the conditions being met.

Syntax

The syntax for pattern matching in F# is as follows:

match expr with
| pat1 - result1
| pat2 -> result2
| pat3 when expr2 -> result3
| _ -> defaultResult

Where,

  • Conditions are defined by the | symbol.
  • A -> symbol indicates “return this value if the condition is true…”
  • _ provides the default pattern, which matches everything like a wildcard.

Pattern Matching Of Season By Month

Here is an example of how a pattern matching of weather season by month can be achieved:

Example: 

let printSeason month = match month with | "December" | "January" | "February" -> printfn "Winter" | "March" | "April" -> printfn "Spring" | "May" | "June" -> printfn "Summer" | "July" | "August" -> printfn "Rainy" | "September" | "October" | "November" -> printfn "Autumn" | _ -> printfn "Season depends on month!"printSeason "December" printSeason "March" printSeason "August" printSeason "June" printSeason "October"

And output will be as:

Winter
Spring
Rainy
Summer
Autumn

Matching on Option type

Below is an example of an option type using pattern matching:

Example: 

let printValue optValue = match optValue with | Some value -> printfn "Value: %d" value | None -> printfn "None"let value1 = Some 22 let noneValue = None let value2 = Some 24printValue value1 printValue noneValue printValue value2

This is what it prints out as a result:

Value: 22
None
Value: 24

Recursive Fibonacci using Pattern Matching

This example prints out the Fibonacci series using the recursive method of pattern matching:

Example: 

let rec fibonacci n = match n with | 0 -> 0 | 1 -> 1 | _ -> fibonacci (n – 1) + fibonacci (n – 2) printfn "Fibonacci Series: \n" for i = 1 to 8 do printf "%d, " (fibonacci i)

And it prints out:

Fibonacci Series:
1, 1, 2, 3, 5, 8, 13, 21,

Pattern Matching Functions

By using the function keyword, you are able to write functions that match patterns using the following syntax:

Example: 

let fruitRate = function | "pineapple" -> 22.00 | "watermelon" -> 19.50 | "mango" -> 25.00 | "orange" -> 12.22 | "apple" -> 8.15 | _ -> nanprintfn "Pineapple: %g"(fruitRate "pineapple") printfn "Watermelon: %g"(fruitRate "watermelon") printfn "Mango: %g"(fruitRate "mango") printfn "Orange: %g"(fruitRate "orange") printfn "Apple: %g"(fruitRate "apple")

And the output will be:

Pineapple: 22
Watermelon: 19.5
Mango: 25
Orange: 12.22
Apple: 8.15

Adding Filters or Guards to Patterns

By using the when keyword, you will be able to add filters, or guards, to patterns.

Example: 

let mathSign = function | 0 -> 0 | a when a < 0 -> -1 | a when a > 0 -> 1printfn "%d" (mathSign 14) printfn "%d" (mathSign -14) printfn "%d" (mathSign 0)

The result prints out the following:

1
-1
0

Comparing numbers by using the when keyword, which is used as an if condition:

Example: 

let compareNum a = match a with | (p, q) when p > q -> printfn "%d is greater than %d" p q | (p, q) when p < q -> printfn "%d is less than %d" p q | (p, q) -> printfn "%d equals %d" p qcompareNum (25,21) compareNum (65, 88) compareNum (3, 3)

And the output will be as follows:

25 is greater than 21
65 is less than 88
3 equals 3

F# Pattern Match With Tuples

The following example shows how tuples can be used to match patterns:

Example: 

let printUserInfo user = match user with | (name, age, city, dob) -> printfn "Name: %s" name printfn "Age: %d" age printfn "City: %s" city printfn "Date of Birth: %s" doblet user1 = ("John", 25, "New York", "18/march/2002") let user2 = ("Ben", 32, "San Antonio","12/august/1998")printUserInfo user1 printUserInfo user2
Output of the above example will be
Name: John
Age: 25
City: New York
Date of Birth: 18/march/2002
Name: Ben
Age: 32
City: San Antonio
Date of Birth: 12/august/1998

Pattern Matching with Lists

Pattern matching in F# can also be used with lists.

You can match on the structure of a list, including its length and individual elements.

Here’s an example of pattern matching with a list:

Example: 

let listLength list = match list with | [] -> 0 | [x] -> 1 | [x; y] -> 2 | _ -> 3

In this example, the listLength function takes a list parameter and matches it against four patterns using the match expression. If the list is empty, the function returns 0. If the list has one element, the function returns 1. If the list has two elements, the function returns 2. If the list has more than two elements, the function returns 3.


Pattern Matching with Records

User records using pattern matching technique:

Example: 

type user = { Name: string Age: int City: string Dob: string }let printUserInfo user = match user with | { Name = name; Age = age; City = city; Dob = dob; } -> printfn "Name: %s" name printfn "Age: %d" age printfn "City: %s" city printfn "Date of Birth: %s \n" doblet user1 = { Name = "John"; Age = 25; City = "New York"; Dob = "18/March/2002";} let user2 = { Name = "Ben"; Age = 32; City = "San Antonio"; Dob = "12/August/1998";}printUserInfo user1 printUserInfo user2

Example Explanation

As a group, we have defined a record type called user with fields Name, Age, City, and Dob which represent user information. We then created a function called printUserInfo that takes a user record as input.

When we call the printUserInfo function with user1, we use pattern matching to destructure the user record into its fields Name, Age, City, and Dob using the record pattern { Name = name; Age = age; City = city; Dob = dob; }. We then print out the values of these fields using the printfn function with appropriate formatting.

User1 output would be:

Name: John
Age: 25
City: New York
Date of Birth: 18/March/2002

Similarly, when we call the printUserInfo function with user2, it prints out the values of the user2 record’s fields in a similar fashion.

User2 would output:

Name: Ben
Age: 32
City: San Antonio
Date of Birth: 12/August/1998

F# Pattern Match Benefits

Here are some benefits of using F# pattern matching:

  • F# Pattern matching allows you to write concise and expressive code that is easy to read and understand. You can match values against patterns, eliminating the need for long if-else or switch statements.
  • Using pattern matching in your code improves readability by making the code more self-documenting. With pattern matching, the code expresses the intent of the developer more clearly, making it easier to understand.
  • F# Pattern matching can help catch errors at compile-time, reducing the likelihood of runtime errors. By matching values against patterns, you can ensure that the code is only executed when the values meet specific conditions.
  • Pattern matching can be more efficient than using if-else or switch statements, as it allows the compiler to generate optimized code. Pattern matching is also less error-prone than using other methods, as it reduces the chance of bugs being introduced.
  • Pattern matching can be used with a wide range of data types, including integers, strings, and user-defined types. You can also use pattern matching with complex data structures, such as lists and arrays.

Conclusion

Pattern matching is a powerful feature in F# that enables you to match values against patterns and perform actions based on the result. In F#, pattern matching is achieved using the match expression. You can match on different types of values, including integers, strings, user-defined types, and lists. Pattern matching in F# allows you to write concise and expressive code, making it an essential tool.

If you liked this article and found it informative regarding F# pattern matching, you can leave your feedback by reacting below.

We value your feedback.
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0

Subscribe To Our Newsletter
Enter your email to receive a weekly round-up of our best posts. Learn more!
icon

Leave a Reply

Your email address will not be published. Required fields are marked *