In this section, we will explore two important type classes in Haskell: Functor and Foldable. These type classes provide powerful abstractions for working with data structures in a functional way.
Functor
What is a Functor?
A Functor is a type class that represents types that can be mapped over. In other words, a Functor is a container that you can apply a function to each element inside it.
Functor Type Class
The Functor type class is defined as follows:
fmapis a function that takes a function(a -> b)and a functorf a, and returns a new functorf bwith the function applied to each element.
Example: Functor Instance for List
Lists are a common example of a Functor. Here’s how the Functor instance for lists is defined:
Using fmap
Here’s an example of using fmap with a list:
-- Define a function to double a number
double :: Int -> Int
double x = x * 2
-- Use fmap to apply the function to each element in the list
doubledList = fmap double [1, 2, 3, 4, 5]
-- Result: [2, 4, 6, 8, 10]Practical Exercise: Functor
Exercise: Implement a Functor instance for a custom data type Maybe.
data Maybe a = Nothing | Just a
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just x) = Just (f x)Solution:
-- Define a function to increment a number
increment :: Int -> Int
increment x = x + 1
-- Use fmap to apply the function to a Maybe value
incrementedMaybe = fmap increment (Just 5)
-- Result: Just 6
incrementedNothing = fmap increment Nothing
-- Result: NothingFoldable
What is Foldable?
Foldable is a type class that represents data structures that can be folded to a summary value. Folding is a way to reduce a data structure to a single value by iteratively applying a function.
Foldable Type Class
The Foldable type class is defined as follows:
foldris a function that takes a binary function(a -> b -> b), an initial accumulator valueb, and a foldable structuret a, and reduces it to a single valueb.
Example: Foldable Instance for List
Lists are also a common example of a Foldable. Here’s how the Foldable instance for lists is defined:
Using foldr
Here’s an example of using foldr with a list:
-- Define a function to sum two numbers
sum' :: Int -> Int -> Int
sum' x y = x + y
-- Use foldr to sum all elements in the list
sumList = foldr sum' 0 [1, 2, 3, 4, 5]
-- Result: 15Practical Exercise: Foldable
Exercise: Implement a Foldable instance for a custom data type Tree.
data Tree a = Empty | Node a (Tree a) (Tree a)
instance Foldable Tree where
foldr _ z Empty = z
foldr f z (Node x left right) = foldr f (f x (foldr f z right)) leftSolution:
-- Define a function to multiply two numbers
multiply :: Int -> Int -> Int
multiply x y = x * y
-- Create a sample tree
sampleTree = Node 1 (Node 2 Empty Empty) (Node 3 Empty Empty)
-- Use foldr to multiply all elements in the tree
productTree = foldr multiply 1 sampleTree
-- Result: 6Summary
In this section, we covered the Functor and Foldable type classes in Haskell. We learned how to use fmap to apply functions to elements inside functors and how to use foldr to reduce foldable structures to a single value. We also implemented custom instances for Maybe and Tree data types to reinforce these concepts.
Next, we will delve into more advanced functional programming concepts, such as Monads, in the following module.
Haskell Programming Course
Module 1: Introduction to Haskell
- What is Haskell?
- Setting Up the Haskell Environment
- Basic Syntax and Hello World
- Haskell REPL (GHCi)
