Haskell - Functor


Advertisements

Functor in Haskell is a kind of functional representation of different Types which can be mapped over. It is a high level concept of implementing polymorphism. According to Haskell developers, all the Types such as List, Map, Tree, etc. are the instance of the Haskell Functor.

A Functor is an inbuilt class with a function definition like −

class Functor f where 
   fmap :: (a -> b) -> f a -> f b 

By this definition, we can conclude that the Functor is a function which takes a function, say, fmap() and returns another function. In the above example, fmap() is a generalized representation of the function map().

In the following example, we will see how Haskell Functor works.

main = do  
   print(map (subtract 1) [2,4,8,16])      
   print(fmap (subtract 1) [2,4,8,16])   

Here, we have used both map() and fmap() over a list for a subtraction operation. You can observe that both the statements will yield the same result of a list containing the elements [1,3,7,15].

Both the functions called another function called subtract() to yield the result.

[1,3,7,15]
[1,3,7,15]

Then, what is the difference between map and fmap? The difference lies in their usage. Functor enables us to implement some more functionalists in different data types, like "just" and "Nothing".

main = do 
   print (fmap  (+7)(Just 10)) 
   print (fmap  (+7) Nothing)

The above piece of code will yield the following output on the terminal −

Just 17
Nothing

Applicative Functor

An Applicative Functor is a normal Functor with some extra features provided by the Applicative Type Class.

Using Functor, we usually map an existing function with another function defined inside it. But there is no any way to map a function which is defined inside a Functor with another Functor. That is why we have another facility called Applicative Functor. This facility of mapping is implemented by Applicative Type class defined under the Control module. This class gives us only two methods to work with: one is pure and the other one is <*>.

Following is the class definition of the Applicative Functor.

class (Functor f) => Applicative f where   
   pure :: a -> f a   
   (<*>) :: f (a -> b) -> f a -> f b   

According to the implementation, we can map another Functor using two methods: "Pure" and "<*>". The "Pure" method should take a value of any type and it will always return an Applicative Functor of that value.

The following example shows how an Applicative Functor works −

import Control.Applicative 

f1:: Int -> Int -> Int 
f1 x y = 2*x+y  
main = do  
   print(show $ f1 <$> (Just 1) <*> (Just 2) ) 

Here, we have implemented applicative functors in the function call of the function f1. Our program will yield the following output.

"Just 4"

Monoids

We all know Haskell defines everything in the form of functions. In functions, we have options to get our input as an output of the function. This is what a Monoid is.

A Monoid is a set of functions and operators where the output is independent of its input. Let’s take a function (*) and an integer (1). Now, whatever may be the input, its output will remain the same number only. That is, if you multiply a number by 1, you will get the same number.

Here is a Type Class definition of monoid.

class Monoid m where  
   mempty :: m 
   mappend :: m -> m -> m  
   mconcat :: [m] -> m 
   mconcat = foldr mappend mempty 

Take a look at the following example to understand the use of Monoid in Haskell.

multi:: Int->Int 
multi x = x * 1 
add :: Int->Int 
add x = x + 0 

main = do  
   print(multi 9)  
   print (add 7)

Our code will produce the following output −

9
7

Here, the function "multi" multiplies the input with "1". Similarly, the function "add" adds the input with "0". In the both the cases, the output will be same as the input. Hence, the functions {(*),1} and {(+),0} are the perfect examples of monoids.

Advertisements