Functions in PureScript
As the name of functional programming suggests it, this style of writing code resolves all around writing functions - so, let’s cover what you need to know.
Writing a function with a return
Section titled “Writing a function with a return”double a = a * 2This functions receives a parameter “a” and returns it (everything behind the equals-sign).
Providing types for the function:
Section titled “Providing types for the function:”double :: Int -> Intdouble a = a * 2This is optional, yet, a best practise.
Writing a function with more than one parameter:
Section titled “Writing a function with more than one parameter:”add :: Int -> Int -> Intadd a b = a + bSince functions are curried, just add another Int -> for each parameter. The code, under the hood looks like this:
function add(a) { return function (b) { return a + b }}Confusing, hm?
Function recursion
Section titled “Function recursion”Recursive is a function that calls itself. This is really useful to write clean code. The following example is a recursive function. It receives a number as starting value, and calls the function as long the number is < 10. Of course, this is absolutely useless, because it makes out of any passed number below 10 a 10 as return.
sumToTen :: Int -> IntsumToTen n = if n == 10 then 10 else sumToTen (n + 1)
main = log (show (sumToTen 0))Result will be “10”.
Higher-order functions
Section titled “Higher-order functions”A higher-order function is a function, that takes another function as a parameter / and or returns another function. This might sound weird at first, but trust me, you used higher-order functions before, and the concept is really powerful. For example, map, filter and reduce as we also have them in JavaScript or Python, are higher-order functions.
Let’s write a function, that takes another function as a parameter:
doubleNum :: Int -> IntdoubleNum n = n * 2
divideByTwo :: (Int -> Int) -> Int -> IntdivideByTwo fun n = (fun n) / 2Our divideByTwo function takes a function with the signature (Int -> Int) as the first parameter. In this functions signature, you can see the () - they always mean we expect a function as a parameter. Then, divideByTwo takes a single Integer, and finally returns an integer. In the definition you can see that we take the providied function and call it “fun”, then pass n to this function.
Now, let’s use the functions:
divideByTwo doubleNum 4--- 4As we undo the multiplication through dividing, the output is 4 again.
Impure functions
Section titled “Impure functions”By definition, pure functions do not change anything outside of their scope. Logging something in the console therefore is an impure function. Of course we can log something from a function, instead of returning a value. This is the case of an impure function:
logSomething :: String -> Effect UnitlogSomething message = log ("My message: " <> message)
main = logSomething "Hello"The do-keyword in functions
Section titled “The do-keyword in functions”The do keyword allows to make code in functions more readable and to work with different expressions. In the following example, “j” and “i” are both expressions, used in a final expression at the bottom which is finally returned.
factors :: Int -> Array (Array Int)factors n = filter (\xs -> product xs == n) do i <- 1 .. n j <- i .. n [ [ i, j ] ]