FP Unit 3
FP Unit 3
FP Unit 3
Prepared By
Ms.Afreen Fatima
Mohammed
Ms.Deepika
Recursive Functions/
Higher-Order Functions/Dealing with Types
Unit - 3
Objectives
• Defining recursion and how it works
• Using recursion to perform advanced tasks and Mixing recursion with functions
• Understanding common recursion errors
• Defining the kinds of data manipulation
• Changing dataset size using slicing, dicing and content using mapping, filtering
• Organizing your data
• Understanding , Creating and managing types
• Fixing type errors
• Using types in code
Using Recursive Functions
• Performing Tasks More than Once
• Understanding Recursion
Performing Tasks More than Once
Defining the need for repetition
•Performing a task a set number of times
•Performing a task a variable number of times until a condition is met
•Performing a task a variable number of times until an event occurs
•Polling for input
•Creating a message pump
•Breaking a large task into smaller pieces and then executing the pieces
•Obtaining data in chunks from a source other than the application
•Automating data processing using various data structures as input
Understanding Recursion
• Considering basic recursion
• Performing tasks using lists
• Upgrading to set and dictionary
Understanding Recursion
• Haskell provides the forM function, which actually has to do with performing I/O
• Control.Monad library contains functions that implement repetition using data
structures as input
• forM processes a list containing four values, passing it to the lambda function that
follows
• The lambda function simply outputs the values using putStrLn and show a
Understanding Recursion in Haskell
• First lets see how a function can be declared in haskell
Considering basic recursion:Haskell
• The technique is the same as the Python example
• The function accepts two inputs,x (the number to append) and n (the number of
times to append it)
• When n is 0,the Haskell code returns an empty list.
• Otherwise, Haskell appends x to the list and returns the appended list.
basic recursion:Haskell
• a
basic recursion:Python
• a
Upgrading to Set and dictionary
Python Haskell
the sets are stored as hashes. sets can’t contain any duplicates and are generally presented
as ordered
myList = [1, 4, 8, 2, 3, 3, 5, 1, 6] import Data.Set as Set
mySet = set(myList) myList = [1, 4, 8, 2, 3, 3, 5, 1, 6]
mySet mySet = Set.fromList(myList)
mySet
{1, 2, 3, 4, 5, 6, 8} fromList [1,2,3,4,5,6,8]
myDic = {"a": 1, "b": 2, "c": 3, "d": 4} let myDic = [("a", 1), ("b", 2), ("c", 3), ("d", 4)]
Python uses a form of index to access individual values, such In Haskell, you might use the lookup function: lookup "b"
as myDic["b"], which also accesses the value 2. myDic, to find that b is associated with 2
myDic = {"A":{"A": 1, "B":{"B": 2, "C":{"C": 3}}}, "D": 4}
Set in Haskell
Set in Python
Dictionary in Python
• a
Using Recursion on Lists:Working with Haskell
• The following code shows how to find the next and previous values in a list:
Using Recursion on Lists:Working with Python
Passing Functions Instead of Variables
• The following code shows the use of Haskell signatures to good effect when
creating functions that accept functions as input:
• The first function simply adds two values; the second subtracts them
• Next step is create the cmp100 function, which accepts a function as the first input
• The next part of the signature shows that the function will receive two integers as
input and provide an order as output
• Next, compare is called with 100 as the first value and the result of whatever
happens in the called function as the second inputFigure 8-9 shows the example
code in action
• Notice that the two numeric input values provide different results, depending on
which function you provide
Passing Functions in Haskell
…contd
Passing Functions in Python
• rem and mod might not seem much different. Using rem 5 3 produces the same output as
mod 5 3 (an output of 2)
• difference arises when working with a negative number. In this situation, mod 3 (-5)
produces an output of -2, while rem 3 (-5) produces an output of 3
Using Python to filter data
• all the filtering in Python requires the use of lambda functions
• The sortBy function lets you use any comparison function needed to obtain the
desired result
• For example, If not interested in sorting by the first member of the tuple but
instead prefer to sort by the second member
• In this case, you must use the snd function from Data.Tuple (which loads with
Prelude) with the comparing function from Data.Ord
Sorting data with Haskell
• original = [(1, "Hello"), (4, "Yellow"), (5, "Goodbye"), (2, "Yes"), (3, "No")],
• The output is sorted by the first member of the tuple: [(1, 'Hello'), (2, 'Yes'), (3,
'No'), (4, 'Yellow'), (5, 'Goodbye')]
• Reversing a list requires the use of the reverse keyword
• Both Haskell and Python make use of lambda functions to perform special sorts
Sorting data with Python
• a
Dealing with Types
Objective
• Developing Basic Types
• Composing Types
• Parameterizing Types
• Dealing with Missing Data
• Creating and Using Type Classes
Developing Basic Types
• Understanding the functional perception of type
• Considering the type signature
• Creating types
• Using AND
• Using OR
• Defining enumerations
• Considering type constructors and data constructors
Developing Basic Types
• Functional languages provide a number of methods for defining type
• Understanding the functional perception of type in Haskell
• When you type :t True and press Enter, you see True :: Bool as output because True is an
expression that produces a Bool output
• To see this perception of type, you use the Python type function. When you type type(1),
you see <class 'int'> as output
• If you create a variable by typing myInt = 1 and pressing Enter, then use the type(myInt)
function, you still see as output.
Considering the type signature: Haskell
• The type signature in Haskell
• the expression findNext (on the left side of the double colon) expects an Int and an
[Int] (list) as input, and provides an Int as output
• A type signature encompasses everything needed to fully describe an expression
and helps relieve potential ambiguity concerning the use of the expression
• Haskell will raise an error if ambiguity exists in the use of an expression and you
don’t provide the required type signature.
Considering the type signature :Python
• Python can also use type signatures, but the philosophy behind Python is different
from that of many other languages
• Consider this function with the type signature:
• The left side is the type constructor, create a type constructor simply by providing a
name, which is CompNum
• The right side is the data constructor, it includes an identifier, Comp, followed by
two Int values
Creating types in Haskell
• To create and test this type, you would use the following code:
• The deriving keyword is important to remember because it makes your life much simpler. The
new data type now works as expected
• Use the deriving keyword to add features to the data type
Using OR in Haskell
• Haskell data types can create a Sum data type — a type that contains multiple
constructors that essentially define multiple associated types
• To create such a type, you separate each data constructor using a bar (|), which is
essentially an OR operator
• The Name type includes a data constructor for Employee that contains fields
named first and last of type String and middle of type Char
Type constructors and Data constructors
• the example uses concatenation (++) to create a single list from the three lists
Monoids
• The associativity law demands that the order in which an operation occurs
shouldn’t matter, but that the order of the individual elements can matter. The
following two lines test both of these criteria:
• The output of the first comparison is True because the order of the concatenation
doesn’t matter
• The output of the second comparison is False because the order of the individual
elements does matter.
Monoids
• The third law, the identity law, requires the use of an empty list, which is equivalent
to the 0 in the set of all numbers that is often used to explain identity.
Consequently, both of these statements are true:
• When performing tasks using some Haskell, you need to use import Data.Monoid
• strings also work just fine as monoids
• as monoids. Note the demonstration of identity using an empty string. In fact, many
Haskell collection types work as monoids with a variety of operators, including
Sequence, Map, Set, IntMap, and IntSet
Monoids
• To make the statement work, you must also call getDual to convert the Dual object
to a standard list
Monoids
• Python collections can also act as monoids.
•
The use of Nothing, Maybe, and Just
• Haskell doesn’t actually have a universal sort of null value. It does have Nothing,
but to use Nothing, the underlying type must support it
• Nothing is actually something, so it’s not actually null
• Nothing is a special kind of value that tells you that the data is missing, without
actually assigning null to the variable
• Normally we don’t assign Nothing to a variable directly. Rather, create a function or
other expression that makes the assignment
• The following example shows a simple function that simply adds two numbers.
However, the numbers must be positive integers greater than 0:
The use of Nothing, Maybe, and Just
• Notice that the type signature has Maybe Int as the output. This means that the
output could be an Int or Nothing
• need to load some support for it:
• To test this how Maybe works, you can try various versions of the function call:
The use of Nothing, Maybe, and Just
• Haskell enables you to process data in unique ways with little code
Understanding semigroups
• Semigroups are like monoids except that they have no identity requirement.
Semigroups actually represent a final level of abstraction
• An example of an object that must use a semigroup is a bounding box. A bounding
box can’t be empty; it must take up some space or it doesn’t exist and therefore the
accompanying object has no purpose
• Another example of when to use a semigroup is Data.List.NonEmpty
• which is a list that must always have at least one entry
• The point is that semigroups have a definite place in creating robust code
Parameterizing Types
• Parameterized types work best when the type acts as a sort of box that could hold
any sort of value
• example for parameterizing types is to create a custom tuple that accepts three
inputs and provides the means to access each member using a special function
• It would be sort of an extension of the fst and snd functions provided by the default
tuple
• this example starts with a real tuple, but of a special kind, Triple
• the example uses a similar, but different, naming strategy of fstT, sndT, and thdT
• Finally, cvtToTuple enables you to change a Triple back into a tuple with three
elements
Parameterizing Types