Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introductory Function Exercises

module Tutorial.Functions1.Exercises

The solutions to these exercises can be found in src/Solutions/Functions1.idr.

Exercise 1

Reimplement functions testSquare and twice by using the dot operator and dropping the second arguments (have a look at the implementation of squareTimes2 to get an idea where this should lead you). This highly concise way of writing function implementations is sometimes called point-free style and is often the preferred way of writing small utility functions.

Exercise 2

Declare and implement function isOdd by combining functions isEven from above and not (from the Idris Prelude). Use point-free style.

Exercise 3

Declare and implement function isSquareOf, which checks whether its first Integer argument is the square of the second argument.

Exercise 4

Declare and implement function isSmall, which checks whether its Integer argument is less than or equal to 100. Use one of the comparison operators <= or >= in your implementation.

Exercise 5

Declare and implement function absIsSmall, which checks whether the absolute value of its Integer argument is less than or equal to 100. Use functions isSmall and abs (from the Idris Prelude) in your implementation, which should be in point-free style.

Exercise 6

In this slightly extended exercise we are going to implement some utilities for working with Integer predicates (functions from Integer to Bool). Implement the following higher-order functions (use boolean operators &&, ||, and function not in your implementations):

-- return true, if and only if both predicates hold
and : (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool

-- return true, if and only if at least one predicate holds
or : (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool

-- return true, if the predicate does not hold
negate : (Integer -> Bool) -> Integer -> Bool

After solving this exercise, give it a go in the REPL. In the example below, we use binary function and in infix notation by wrapping it in backticks. This is just a syntactic convenience to make certain function applications more readable:

Tutorial.Functions1> negate (isSmall `and` isOdd) 73
False

Exercise 7

As explained above, Idris allows us to define our own infix operators. Even better, Idris supports overloading of function names, that is, two functions or operators can have the same name, but different types and implementations. Idris will make use of the types to distinguish between equally named operators and functions.

This allows us, to reimplement functions and, or, and negate from Exercise 6 by using the existing operator and function names from boolean algebra:

-- return true, if and only if both predicates hold
(&&) : (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool
x && y = and x y

-- return true, if and only if at least one predicate holds
(||) : (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool

-- return true, if the predicate does not hold
not : (Integer -> Bool) -> Integer -> Bool

Implement the other two functions and test them at the REPL:

Tutorial.Functions1> not (isSmall && isOdd) 73
False