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: Nothing
Foldable
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: 15
Practical 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: 6
Summary
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)
