Friday 29 April 2016

Haskell: Lambda: Anonymous functions

Lambdas are anonymous functions (don't have name), used in situations where you want to use function only once.

How to define a lambda?
Lambda is created by using \ followed by parameters, separated by spaces. After that comes a -> and then the function body.
Following snippet calculates the sum of three numbers.

*Main> let sum = \x y z -> (x+y+z) 
*Main> 
*Main> sum 10 20 30
60
*Main>


You can also define lambda parameters by using parenthesis like below.

*Main> let sum = \(x, y, z) -> (x+y+z) 
*Main> 
*Main> sum(10,20,30)
60


Following lambda swap two elements.

*Main> let swap = \x y -> (y, x)
*Main> 
*Main> swap 10 20
(20,10)


You can also apply pattern matching in lambda expressions.

*Main> let tail_list = (\ (_:xs) -> xs)
*Main> 
*Main> tail_list [2, 3, 5, 7]
[3,5,7]


Difference between lambda and normal functions
We can write normal functions using multiple clauses like guards, cases, if-else etc.,but a lambda can have only a single clause in its definition.

*Main> let tail = \(x:xs) -> xs
*Main> tail [1, 2, 3, 4, 5]
[2,3,4,5]
*Main> 
*Main> tail []
*** Exception: <interactive>:12:12-24: Non-exhaustive patterns in lambda


Observe above snippet, I defined tail function using lambda, since lambdas don't support multiple clauses, I can't handle the empty list condition here.

Example
a. map (\x -> x*x) [1, 2, 3]
Double every element of a list

b. map (\(x, y) -> x+y) [(1, 2), (3, 4), (5, 6)]
Retun a list, that contains sum of elements of every tuple.

*Main> map (\x -> x*x) [1, 2, 3]
[1,4,9]
*Main> 
*Main> map (\(x, y) -> x+y) [(1, 2), (3, 4), (5, 6)]
[3,7,11]


Restrictions on Anonymous functions
a. Anonymous functions don’t have name, so you can’t apply recursion on it.

b. In anonymous function, you can able to match only one pattern, to match multiple pattern you should use case statement.

FunctionUtil.hs

welcome :: [String] -> [String]
welcome persons = map (\name -> case name of
    "Hari" -> "Hello Hari"
    "PTR" -> "Welcome PTR"
    x -> "Have a good day " ++ x) persons


*Main> :load FunctionUtil.hs 
[1 of 1] Compiling Main             ( FunctionUtil.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> welcome ["Phalgun", "Hari", "Sankalp", "PTR"]
["Have a good day Phalgun","Hello Hari","Have a good day Sankalp","Welcome PTR"]
*Main> 


If you are using GHCi, By enabling lambda case extensions (:set -XLambdaCase), You can simplify the code like below.


FunctionUtil.hs

welcome :: [String] -> [String]
welcome persons = map (\case
    "Hari" -> "Hello Hari"
    "PTR" -> "Welcome PTR"
    x -> "Have a good day " ++ x) persons


*Main> :set -XLambdaCase
*Main> 
*Main> :load FunctionUtil.hs 
[1 of 1] Compiling Main             ( FunctionUtil.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> welcome ["Phalgun", "Hari", "Sankalp", "PTR"]
["Have a good day Phalgun","Hello Hari","Have a good day Sankalp","Welcome PTR"]
*Main> 



Previous                                                 Next                                                 Home

No comments:

Post a Comment