Saturday 30 April 2016

Haskell: filter function


Filter pattern is one of the frequently used patterns in functional programming. By using filter pattern, you can filter elements from a sequence.

For example, you want to
a.   Remove all even numbers from a list
b.   Remove all odd numbers from a list
c.    Remove all numbers that are > 100

You implement like below.

filterEx.hs
{- Remove all even numbers from a list -}
removeEven :: [Integer] :: [Integer]
removeEven [] = []
removeEven (x:xs)
    | odd x = x : removeEven xs
    | otherwise = removeEven xs


{- Remove all odd numbers from a list -}
removeOdd :: [Integer] :: [Integer]
removeOdd [] = []
removeOdd (x:xs)
    | odd x = x : removeOdd xs
    | otherwise = removeOdd xs

{- Remove all numbers that are > 100 -}
removeGt100 :: [Integer] :: [Integer]
removeGt100 [] = []
removeGt100 (x:xs)
    | (x < 100) = x : removeGt100 xs
    | otherwise = removeGt100 xs

Prelude> :load filterEx.hs
[1 of 1] Compiling Main             ( filterEx.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> removeEven [2, 5, 123, 45, 66, 21]
[5,123,45,21]
*Main> 
*Main> removeOdd [2, 5, 123, 45, 66, 21]
[5,123,45,21]
*Main> 
*Main> removeGt100 [2, 5, 123, 45, 66, 21]
[2,5,45,66,21]
*Main>


By using filter pattern, you can implement the same functions like below.

filterEx.hs
isLt100 num = (num < 100)

removeGt100 xs = filter isLt100 xs
removeEven xs = filter odd xs
removeOdd xs = filter even xs

Prelude> :load filterEx.hs
[1 of 1] Compiling Main             ( filterEx.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> removeEven [2, 5, 123, 45, 66, 21]
[5,123,45,21]
*Main> 
*Main> removeGt100 [2, 5, 123, 45, 66, 21]
[2,5,45,66,21]
*Main> 
*Main> removeOdd [2, 5, 123, 45, 66, 21]
[2,66]
*Main>
 
The implementation for filter pattern looks like below.
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
  | p x       = x : filter p xs
  | otherwise = filter p xs


Example 1: Return an element from list that satisfies given predicate.

ListUtil.hs
getElement :: (a -> Bool) -> [a] -> Maybe a
getElement predicateFun list =  myFilter predicateFun list
    
myFilter :: (a -> Bool) -> [a] -> Maybe a
myFilter p [] = Nothing
myFilter p (x:xs)
    | p x = Just x
    | otherwise = myFilter p xs

Prelude> :load ListUtil.hs
[1 of 1] Compiling Main             ( ListUtil.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> getElement even [1, 2, 3, 4, 5]
Just 2
*Main> getElement odd [ 2, 6, 3, 4, 5]
Just 3
*Main> getElement odd [ 2, 6]
Nothing
*Main> getElement odd []
Nothing
*Main> :t getElement
getElement :: (a -> Bool) -> [a] -> Maybe a


Example 2: Return all the elements from list that satisfies given predicate.

ListUtil.hs
getElements :: (a -> Bool) -> [a] ->  [a]
getElements predicateFun list =  myFilter predicateFun list
    
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter p [] = []
myFilter p (x:xs)
    | p x = x:myFilter p xs
    | otherwise = myFilter p xs

*Main> :load listUtil.hs
[1 of 1] Compiling Main             ( listUtil.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> getElements odd [2, 3, 5, 4, 6, 17, 19]
[3,5,17,19]
*Main> 
*Main> getElements even [2, 3, 5, 4, 6, 17, 19]
[2,4,6]
*Main> 
*Main> getElements even []
[]
*Main>


Example 3: Get index of element that satisfies given predicate.

ListUtil.hs
getIndex :: (a -> Bool) -> [a] ->  Maybe Int
getIndex predicateFun list =  myFilter predicateFun list 0
    
myFilter :: (a -> Bool) -> [a] -> Int -> Maybe Int
myFilter _ [] _= Nothing
myFilter p (x:xs) index
    | p x = Just index
    | otherwise = myFilter p xs (index+1)

Prelude> :load listUtil.hs
[1 of 1] Compiling Main             ( listUtil.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> getIndex odd [2, 3, 5, 4, 6, 17, 19]
Just 1
*Main> getIndex even [2, 3, 5, 4, 6, 17, 19]
Just 0
*Main> getIndex even []
Nothing
*Main> 
*Main> :t getIndex
getIndex :: (a -> Bool) -> [a] -> Maybe Int
*Main> 
 
Example 4: Get all indexes of elements in list that satisfies given predicate.

ListUtil.hs
getIndexes :: (a -> Bool) -> [a] ->  [Int]
getIndexes predicateFun list =  myFilter predicateFun list 0
    
myFilter :: (a -> Bool) -> [a] -> Int -> [Int]
myFilter _ [] _= []
myFilter p (x:xs) index
    | p x = index : myFilter p xs (index+1)
    | otherwise = myFilter p xs (index+1)


*Main> :load listUtil.hs
[1 of 1] Compiling Main             ( listUtil.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> getIndexes odd [2, 3, 5, 4, 6, 17, 19]
[1,2,5,6]
*Main> getIndexes even [2, 3, 5, 4, 6, 17, 19]
[0,3,4]
*Main> getIndexes even []
[]


 
Previous                                                 Next                                                 Home

No comments:

Post a Comment