-
Notifications
You must be signed in to change notification settings - Fork 0
/
06HigherOrderFunctions.hs
59 lines (52 loc) · 2.68 KB
/
06HigherOrderFunctions.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
-- Sum the numbers between two inclusive values recursively, assuming a < b when the function is first called
-- Example: sumInts 0 1 = 1
-- sumInts 1 3 = 6
sumInts :: Int -> Int -> Int
sumInts a b = sumInts' [a..b]
sumInts' :: [Int] -> Int
sumInts' [] = 0
sumInts' [x] = x
sumInts' (x:xs) = x + sumInts' xs
-- Define a square function
sq :: Int -> Int
sq x = x*x
-- Sum the squares between two numbers. This function should be similar to the sumInts function
sumSquares :: Int -> Int -> Int
sumSquares a b = sumSquares' (map sq [a..b])
sumSquares' :: [Int] -> Int
sumSquares' x = sumInts' x
-- Define a higher order sum function which accepts an (Int -> Int) function to apply to all integers between two values.
-- Again this should look similar to the sumInts and sumSquares functions
higherOrderSum :: (Int -> Int) -> Int -> Int -> Int
higherOrderSum intApplication a b =
let list = map (intApplication) [a..b]
in sumInts' list
-- Define the square sum in terms of higherOrderSum
hoSumSquares :: Int -> Int -> Int
hoSumSquares a b = higherOrderSum (sq) a b
-- Define the sum between two values in terms of higherOrderSum
-- Note there is no parameter on the function definition
-- Try to use a lambda if possible
hoSumInts :: Int -> Int -> Int
hoSumInts = higherOrderSum (\x -> x*1)
-- Create a new higher order method which generalises over the function provided by sumInts (That is, parameterize (+) :: Int -> Int -> Int) between a and b
-- This will give the ability to perform utilities such as the product of all squares (or any other Int -> Int function) between a and b
-- You will also need to generalise the base case
-- You can also define the function signature yourself, which leaves you free to define the parameters and their order
-- To be clear, your function will need to handle:
-- - A start value, a :: Int
-- - A end value, b :: Int
-- - A function to apply to each value, op :: Int -> Int
-- - A function to apply between each value, f :: Int -> Int -> Int
-- - A value to return in the base case when a > b, z :: Int
higherOrderSequenceApplication :: (Int -> Int) -> (Int -> Int -> Int) -> Int -> Int -> Int
higherOrderSequenceApplication appFun betweenFun intA intB
| intA == intB = appFun intA
| otherwise =
let (x:xs) = map appFun [intA..intB]
in x `betweenFun` higherOrderSequenceApplication appFun betweenFun (intA + 1) intB
-- Define a factorial method using the higherOrderSequenceAppliction
hoFactorial :: Int -> Int
hoFactorial intA
| intA == 0 = 1
| otherwise = higherOrderSequenceApplication (*1) (*) 1 intA