How to Use Pattern Matching In Haskell?

11 minutes read

Pattern matching is a fundamental feature of Haskell that allows you to deconstruct complex data structures using concise and elegant syntax. It helps you write more readable and maintainable code by directly extracting values from data structures and performing different computations based on the structure and content of the data.


To use pattern matching in Haskell, you define functions with multiple equations, each specifying different patterns to match and corresponding actions to take. These equations are tried in order, from top to bottom, until a matching pattern is found.


The most common use of pattern matching is with algebraic data types, which are defined using the data keyword. You can match on constructors of these types to access the data they contain. For example, given a Person type defined as data Person = MkPerson String Int, you can match on the MkPerson constructor to extract the name and age:

1
2
showPerson :: Person -> String
showPerson (MkPerson name age) = "Name: " ++ name ++ ", Age: " ++ show age


In this example, the pattern (MkPerson name age) matches any value constructed with the MkPerson constructor, and the variables name and age capture the values contained within.


Pattern matching is not limited to data types; you can also match on primitive types like Int, Char, or Bool, as well as lists, tuples, and more complex structures. For example, you can match on a list to perform different computations based on its length:

1
2
3
listLength :: [a] -> Int
listLength [] = 0
listLength (_:xs) = 1 + listLength xs


In this example, the pattern [] matches an empty list, and the pattern (_:xs) matches a non-empty list, where _ is used to ignore the value of the head of the list, and xs captures the tail.


Pattern matching can also be used with guards, which are additional conditions that must be satisfied for a pattern to match. Guards allow you to further refine your patterns based on arbitrary Boolean expressions. For example:

1
2
3
4
factorial :: Int -> Int
factorial n
    | n == 0    = 1
    | otherwise = n * factorial (n - 1)


In this example, the pattern n == 0 matches when n is equal to zero, and the otherwise guard matches any other value of n. The corresponding computations are performed based on the matching patterns.


Pattern matching is a powerful tool in Haskell that enables you to write expressive and concise code by directly extracting values and their structure. It is extensively used in Haskell programming due to its ability to handle complex data structures and ensure type safety.

Best Haskell Books to Read in 2024

1
Programming in Haskell

Rating is 5 out of 5

Programming in Haskell

2
Get Programming with Haskell

Rating is 4.9 out of 5

Get Programming with Haskell

3
Real World Haskell

Rating is 4.8 out of 5

Real World Haskell

4
Parallel and Concurrent Programming in Haskell: Techniques for Multicore and Multithreaded Programming

Rating is 4.7 out of 5

Parallel and Concurrent Programming in Haskell: Techniques for Multicore and Multithreaded Programming

5
Haskell from the Very Beginning

Rating is 4.6 out of 5

Haskell from the Very Beginning

6
Programming in Haskell

Rating is 4.5 out of 5

Programming in Haskell


How to use pattern matching in Haskell for guards?

Pattern matching in Haskell is a powerful way to define functions based on the structure of input values. Guards, on the other hand, are used to specify conditions that need to be satisfied for a particular pattern match to take effect. Combining pattern matching with guards allows you to define functions that behave differently based on certain conditions.


Here's an example of how you can use pattern matching with guards in Haskell:

1
2
3
4
5
myFunction :: Int -> String
myFunction n
  | n == 0 = "Zero"
  | n > 0  = "Positive"
  | n < 0  = "Negative"


In this example, the function myFunction takes an Int as input and returns a String based on the value of the input. The pattern matching takes place in the function definition itself, where the different cases are distinguished based on the value of n. Each case is followed by a guard, which is denoted by the | symbol. Guards are conditions that need to be satisfied for that particular pattern match to proceed.


In this specific example, we have three cases:

  • If n is equal to zero, then the guard n == 0 is satisfied, and the function returns the string "Zero".
  • If n is greater than zero, then the guard n > 0 is satisfied, and the function returns the string "Positive".
  • If n is less than zero, then the guard n < 0 is satisfied, and the function returns the string "Negative".


Note that the cases are evaluated from top to bottom, and the first matching case is executed. Therefore, it is important to order the cases correctly, otherwise some cases might never be reached.


Pattern matching with guards allows you to define more complex functions by combining pattern matching with conditional logic. You can use multiple guards in a single case, and you can also include additional patterns to match against within each case.


How to use pattern matching in Haskell for tuple patterns?

In Haskell, you can use pattern matching to extract values from tuples. Here's an example of how you can do it:

1
2
3
4
tuplePatternMatching :: (Int, String) -> String
tuplePatternMatching (1, "hello") = "Tuple matches (1, \"hello\")"
tuplePatternMatching (2, _) = "Tuple matches (2, Anything)"
tuplePatternMatching (x, y) = "Tuple doesn't match any of the patterns"


In this example, tuplePatternMatching takes a tuple (Int, String) as a parameter. There are three patterns being matched:

  1. If the tuple is (1, "hello"), the function returns the string Tuple matches (1, "hello").
  2. If the tuple is (2, _), where the second value can be anything, the function returns the string Tuple matches (2, Anything).
  3. If the tuple doesn't match any of the patterns listed, the function returns the string Tuple doesn't match any of the patterns.


You can test this function with different tuples:

1
2
3
tuplePatternMatching (1, "hello")       -- Outputs: "Tuple matches (1, \"hello\")"
tuplePatternMatching (2, "world")       -- Outputs: "Tuple matches (2, Anything)"
tuplePatternMatching (3, "hello world") -- Outputs: "Tuple doesn't match any of the patterns"


Pattern matching on tuples allows you to destructure the tuple and handle different cases based on its values.


How to use pattern matching in Haskell for custom data types?

Pattern matching in Haskell is a powerful feature that allows you to deconstruct and operate on values of custom data types. Here's how you can use pattern matching on custom data types in Haskell:

  1. Define a data type: To demonstrate pattern matching, let's define a simple data type called Shape that represents different geometric shapes:
1
2
data Shape = Circle Float      -- Circle with radius
           | Rectangle Float Float  -- Rectangle with length and width


  1. Define a function that uses pattern matching: Let's define a function area that calculates the area of a shape:
1
2
3
area :: Shape -> Float
area (Circle radius) = pi * radius * radius
area (Rectangle length width) = length * width


  1. Use the function: Now, you can use the area function to calculate the area of different shapes:
1
2
circleArea = area (Circle 5.0)                -- 78.53982...
rectangleArea = area (Rectangle 2.0 3.0)      -- 6.0


In the area function, we match the Shape input against the different constructors. If the shape is constructed using the Circle constructor, we extract the radius value and calculate the area using the formula pi * radius * radius. Similarly, if the shape is constructed using the Rectangle constructor, we extract the length and width values and calculate the area using length * width.


Pattern matching can also be used in pattern guards, where you can include additional conditions for the patterns. You can pattern match on multiple arguments, nested data structures, and even combine multiple patterns using guards or the | symbol.


How to use pattern matching in Haskell to handle empty lists?

In Haskell, pattern matching is a powerful feature that allows you to deconstruct data structures and handle different cases individually. When dealing with empty lists, you can use pattern matching to handle them in a specific way. Here's an example of how to use pattern matching in Haskell to handle empty lists:

  1. Using a function definition with pattern matching:
1
2
3
myFunc :: [a] -> String
myFunc [] = "List is empty"
myFunc (x:xs) = "List is not empty"


In this example, the myFunc function takes a list as input [a] and pattern matches against it using empty brackets [] to represent an empty list. If the input list is empty, the first pattern will match and return the string "List is empty". If the list is not empty, the second pattern (x:xs) will match, where x represents the first element and xs represents the rest of the list. You can handle both cases differently based on your requirements.

  1. Using case expressions:
1
2
3
4
myFunc :: [a] -> String
myFunc xs = case xs of
  [] -> "List is empty"
  (x:xs) -> "List is not empty"


In this case, you can use case expressions to pattern match against the input list xs. The first pattern [] matches an empty list and returns "List is empty". The second pattern (x:xs) matches a non-empty list, where x represents the first element and xs represents the remaining elements. Similarly, you can handle each case accordingly.


By using pattern matching in Haskell, you can easily handle empty lists and apply specific logic or behavior based on whether the list is empty or not.

Facebook Twitter LinkedIn Telegram

Related Posts:

Regular expressions, also known as regex, can be used in Haskell for pattern matching and searching within strings. If you want to use regex to match an integer in Haskell, there are a few steps to follow:Import the necessary modules: Begin by importing the Te...
To use libraries and packages in Haskell, you need to follow these steps:Install the Haskell build tool, Cabal, on your system. Cabal allows you to easily manage dependencies and build Haskell projects. Identify the library or package you want to use. You can ...
Exception handling in Haskell is quite different from most other programming languages. Haskell, being a purely functional language, discourages the use of exceptions for flow control. However, exceptions can still occur in Haskell due to runtime errors or exc...