In a similar manner to the function
add
, define a recursive multiplication functionmult :: Nat -> Nat -> Nat
for the recursive type of natural numbers:Hint: make use of add in your definition.
data Nat = Zero | Succ Nat
deriving stock Show
add :: Nat -> Nat -> Nat
Zero n = n
add Succ m) n = Succ (add m n)
add (
mult :: Nat -> Nat -> Nat
Zero _ = Zero
mult Succ m) n = add n (mult m n) mult (
We can introduce new names for types that we already have by means of the type
keyword. As an example, if we wanted to think of an ordered pair of integers as some position, we could do so by writing type Pos = (Int, Int)
and we might declare a transformation as a function which maps a Pos
to another Pos
: type Trans = Pos -> Pos
.
Note: the name of the newly declared type must be capitalized.
Show how the list comprehension
[f x | x <- xs, p x]
can be re-expressed using the higher order functionsmap
andfilter
.
applyFilterAndFnToList :: (a -> Bool) -> (a -> b) -> [a] -> [b]
= map f (filter p xs) applyFilterAndFnToList p f xs
Functions with multiple arguments are defined with currying (which is part of why we have right-associative groupings for parameters). As an example, we can rewrite
add :: Int -> Int -> Int
= x + y add xy
as
add :: Int -> (Int -> Int)
= \x -> (\y -> x + y) add
which makes it clear that add is a function that takes an integer and returns another function which takes an integer and maps to the sum x + y
.
Functions can be defined in terms of themselves. When a function is self-referential, we say that it is recursive. Consider the explicit and recursive definitions of the factorial function:
facExplicit :: Int -> Int
= product [1..n]
facExplicit n
facRecursive :: Int -> Int
0 = 1
facRecursive = n * facRecursive (n - 1) facRecursive n
How does the recursive version of the factorial function behave if applied to a negative argument, like β ββ 1? Modify the definition to prohibit negative arguments by adding a guard to the recursive case.
facRecursive :: Int -> Int
facRecursive n| n < 0 = 0
| n == 0 = 1
| otherwise = n * facRecursive (n - 1)
In mathematics, we can construct a set with a generator. If we wanted to create the set of all odd numbers, we could use the set-builder notation {2kβ +β 1|xββββ€+}.
Haskell presents a similar opportunity, but it calls it a list comprehension. If we were to want to build a list of the first 10 perfect squares, we could do
> [x^2 | x <- [1..10]]
1,4,9,16,25,36,49,64,81,100] [
Using a list comprehension, give an expression that calculates the sum 12β +β 22β +β β¦β +β 1002 of the first one hundred integer squares.
sum100ConsecSquares :: Int
= sum [x^2 | x <- [1..100]] sum100ConsecSquares
Function composition is an extremely powerful tool and should not be overlooked. If it works for Unix, itβll probably work for you.
Using library functions, define a function
halve :: [a] -> ([a],[a])
that splits an even-lengthed list into two halves. For example:> halve [1,2,3,4,5,6] 1,2,3],[4,5,6]) ([
halve :: [a] -> ([a],[a])
= splitAt (((length xs) + 1) `div` 2) xs halve xs