($)
operatorgroup
and groupBy
on
functioncompare
and Ordering
maximumBy
, minimumBy
, and sortBy
Prelude.flip
We have already used functions. Now we will create functions.
This function takes one parameter (x
) and produces a value.
Function with two parameters. The names of the parameters are a
and b
. The type of a
is Integer
and the type of b
is Integer
. The value produced by the function is Integer
. We use ::
operator to explicitly give the type of the function, where ->
separates the types of the parameters and the result value. We pronounce this as “Integer to Integer to Integer”.
Generate the following list: [1, 2, …, n-1, n, n-1, …, 2, 1]
Given sides of a triangle as a
, b
, c
, decide whether the given triangle can be constructed.
Redefine the even
function from the Prelude
module, which determines a given integer is even.
Redefine the odd
function from the Prelude
module, which determines a given integer is odd.
Define the divisibility.
Calculate the sum of squares from 1
to n
.
Define a function, which given an integer n, returns the positive divisors of n!
Define a function that generates a list of proper divisors for a given number.
Operators are functions whose name consists of symbols. We have used many operators, such as ++
and /
. Operators can be defined just a functions. However, note that the name of the operator must be enclosed in parentheses in the type signature.
We can now use this operator with infix notation:
A function definition may consist of multiple equation lines. If one equation line cannot be matched against the input, the next will be tried.
isUserNameValid :: String -> Bool
isUserNameValid "" = False -- blank user name is wrong
isUserNameValid "root" = False -- reserved user name is wrong
isUserNameValid _ = True -- anything else is okay
Note that _
, like a parameter name, will match any value.
And its use:
What happens if we ask for inWords 5
?
Here we define the operator &&
with pattern matching.
Simplified version:
Alternative simplified version:
Redefine logical OR.
Define swap
!
Let scale' t
be scaling from origin by t
.
Calculate the distance of two points.
You can use the absolute value function:
You can use the square root function:
Define modulo 3 multiplication. This means that for every x
and y
between 0 and 3, this expression will be true:
x `mul3` y == (x * y) `mod` 3
Use pattern matching to achieve this. Do not use the mod
function or multiplication operator in your solution!
Define a function that replaces a line break with a space, and otherwise returns the same value. Recall that ‘’ is the character value for a newline.
Define a function that replaces all line breaks with spaces. Use replaceNewline
.
Define a function that replaces the words “this” and “that” and vice versa.
Define a function that swaps all instances of “this” and “that”.
Hint: Use the words
and unwords
functions.
Empty list pattern: []
Non-empty list pattern: a:
b
Other list patterns: [
a]
, [
a,
b]
, …
Examples:
Define a function that tests the given list is a singleton one. Use pattern matching.
Redefine sum
!
Redefine Prelude.last
, which returns the last element of a list!
Redefine Prelude.init
, which returns all but the last element of a list!
This is equivalent to:
Make a lowercase letter uppercase and an uppercase letter lowercase with the upperLower
function.
Hint. Use isUpper
, isLower
, toUpper
, toLower
.
Let sqr
be the squaring function:
Redefine the (^)
operator!
Definition of drop
:
Usage:
Redefined Prelude.take
, which returns the first n elements of a list.
Example with bindings:
unzip :: [(a, b)] -> ([a], [b])
unzip [] = ([], [])
unzip ((a, b): xs) = (a:as, b:bs)
where (as, bs) = unzip xs
Redefine Prelude.splitAt
which splits a list at the nth position!
Sections are functions made from operators: (<3)
, (^2)
, (4*)
.
Note: Use (+(-4))
instead of (-4)
which is a literal.
A higher-order function is a function that takes another function as a parameter. Here is a trivial example:
A better example:
Usage:
Another example:
Define count
which counts elements with a given property.
Redefine Prelude.takeWhile
which returns the longest prefix (possibly empty) of the given list of elements that satisfy the given property.
Redefine the universal quantification (Prelude.all
).
Redefine the existential quantification (Prelude.any
).
Define the membership function (with the help of any
) that determines if an element is member of a list.
Redefine the Prelude.zipWith
function.
Note that the constructor for pairs is as follows.
Therefore it is possible to write (,) 2 'c'
, but instead we often use the form (2,'c')
. Although, sometimes the (,)
notation is definitely useful. For example, here is an alternative definition for the zip
function.
With the use of zipWith
, implement a function that produces the sequence of pairwise differences of elements for a list.
Redefine the Prelude.span
function that could be expressed in the following way:
Implement this function in a more efficient manner.
Implement the Data.List.group
function. This function splits a list into smaller sections that all contains equivalent elements.
Hint. Use the span
function.
Define the compress
function that finds all repeated elements in a list and packs them together with the number of their occurences as pairs.
Hint. Use the group
function.
Redefine the Prelude.uncurry
function that translates a two-parameter function to a function that operates on pairs.
Remark. The inverse operation is the Prelude.curry
function.
Define decompress
, the inverse operation for the previously defined compress
function. This is to unpack the list of pairs containing elements associated with the number of their occurences into an uncompressed list.
Redefine Prelude.iterate
that iterates a function on a given element.
($)
operatorThis operator forces evaluation of values to its right. You can use it instead of parentheses in some cases.
Use case:
Same as:
A lambda function is an unnamed function. The body of the function is given instead of its name.
Instead of this:
We can write this:
In Mathematics: x ↦ x + 1
Define the sequence of Fibonacci pairs:
(0,1), (1,1), (1,2), (2,3), (3,5), (5,8), ...
Hint. Use the following production rule: (a, b) ↦ (b, a + b).
group
and groupBy
Note that Data.List.group
is actually expressed as the follows.
Inspect the type and semantics of this groupBy
function.
Let f
be a (two-parameter predicate) function of type a -> a -> Bool
. For all x
, y
, and z
where f x y
, f y z
, and f x z
holds, groupBy f
sticks all the subsequent elements together where f
is true.
on
functionObserve the type of the Data.Function.on
function and redefine it.
Define a function for extracting numbers from a string.
compare
and Ordering
The compare
function is defined for every type that is a member of the Ord
type class.
Ordering
is a ternary data type, and it has the following constructors: LT
for “less than”, EQ
for “equals”, and GT
for “greater than”.
maximumBy
, minimumBy
, and sortBy
There are many other “by” functions that could be used in conjunction with compare
. Such functions are the higher-order versions of their standard counterparts with the difference that the way of comparison could be set by function argument.
Prelude.flip
Redefine the flip
function. This is to flip the order of the arguments for a two-parameter function.
Find the longest word in a string.
Determine which character occurs the most in a string.
Determine at which index is the greatest element in the list. (The indexing shall start from 1.)
Definition:
Alternative definition:
Construct the sequence 1, 11, 111, 1111, …
Define double map with function composition.
Define monogram
.
Implement the function named uniq
(as a composition) that eliminates all the redudant elements from a list.
Hint. Here is how it shall work:
Let repeated
be a (composed) function that determines what elements occur more than once in a list.
Hint. Here is how it shall work:
Redefine the Prelude.until
function (as a composition).
Left and right folds:
Types:
Redefine Prelude.minimum
in terms of some fold and min
.
Left and right folds:
Types:
Redefine Prelude.product
in terms of a fold.
Redefined Prelude.and
in terms of a fold.
This is the same as this:
Here is how we use it:
Try these functions yourself. Make sure you understand how they work.
A scan is similar to a fold, but it returns a value for each application in the input list. In this way, a scan can help us understand how fold-based algorithms work. For example, consider, the isort
function above. If we replace foldr
with scanr
, we can see step of insertion sort, in reverse order: