# Values and functions exercises

A few exercises relevant to values and functions.

๐Exercise: Understand parentheses in type signatures

List.zipWithis a function which takes in two lists and a function which operates on the elements in both lists sequentially until the end of one of the lists is reached.

A mysterious parenthesis blight has wiped away the necessary parentheses to communicate this.

blightedZipWith: a -> b -> c -> [a] -> [b] -> [c]

Where should the parentheses in the type signature go? Where should the implied parentheses go for this type signature?

โจHint
โจHint
threeArgumentFunction : Nat -> Text -> Boolean -> Nat

Is analogous to

threeArgumentFunction: Nat -> (Text -> (Boolean -> Nat))

It's easy to conflate the order of functionapplication(the order in which a function is called) with the order of its type notation. Here we're looking for a description of where to draw the implied and actual parentheses for how the function arrow->works in a type signature.

The required parentheses are as follows:

zipWith: (a -> b -> c) -> [a] -> [b] -> [c]

The first argument toList.zipWithis a function with two argumentsaandb.Lists[a]and[b]are the two lists being zipped, and[c]is the return type of the over all function.

Adding the implied parentheses for the type signature yields:

zipWith: ((a -> (b -> c)) -> ([a] -> ([b] -> [c])))

๐Exercise: Understand parentheses when calling functions

A similar parenthesis blight has afflicted the site where we're calling our function. Add both the implied and necessary parentheses to the following code

use Nat
listA = [1,2,3,4,5]
listB = [2,4,6,8,10]

fixMe = List.zipWith a -> b -> a + b listA listB

The required parentheses are as follows:

use Nat
listA = [1,2,3,4,5]
listB = [2,4,6,8,10]

fixMe = List.zipWith (a -> b -> a + b) listA listB

Adding the implied parentheses for the order in which function application occurs:

use Nat
listA = [1,2,3,4,5]
listB = [2,4,6,8,10]

fixMe = ((List.zipWith (a -> b -> a + b) listA) listB)

๐Exercise: Determine a type signature for a function from how it's called

Write the signature forList.foldLeftgiven the following information:

An example of how foldLeft is called is

List.foldLeft
(acc i -> Text.size i Nat.+ acc) 0 ["a", "bb", "ccc", "ddd"]โงจ9

You can read about whatList.foldLeftdoes by reading the docs linked here:base.List.foldLeft.docor by entering docs List.foldLeft in the UCM.

โจHint
โจHint
Our example uses a functionText.sizeto transformTextinto a number, and then adds the length of each text element together, butList.foldLeftshould be polymorphic--that is, it should not care if it is operating on is a List of Text, or a List of Char or a List of Boolean.
โจHint
โจHint

The first argument toList.foldLeftis a function with two arguments, the first is the value that is being accumulated as the fold function is operating on each element on the list, the second corresponds to the element of the list.

The second argument to theList.foldLeftfunction is the value that should be applied when the higher order function encounters the end of the list.

The third argument to List.foldLeft is the list being folded over.

Note, the actual signature ofList.foldLeftcontains a parameter in curly braces,{e}.List.foldLeftisability polymorphic,meaning that the step function provided to it can perform effects. We'll be covering those later in our section on Abilities.

List.foldLeft : (b ->{๐} a ->{๐} b) -> b -> [a] ->{๐} b

๐Exercise: Debug a Unison function which fails to typecheck

brokenFactorial : Nat -> Nat
brokenFactorial n =
use Universal Nat
if n === 0 then 1 else n * brokenFactorial drop n 1

We'll cover the use keyword later, we're using it above to disambiguate a few function names.

Something is wrong with this function. It does not typecheck, and the UCM prints out the following error. See if you can fix it.

This looks like a function call, but with a Nat where the function should be.  Are you missing an operator?

4 |   if n === 0 then 1 else n * brokenFactorial drop n 1
โจHint
โจHint
โจHint
โจHint
What is the order of function application in theelseclause?

Due to the order of function application, we need to surround the call todrop n 1with parentheses.

factorial : Nat -> Nat
factorial n =
if n === 0 then 1
else
use Nat * -
n * factorial (n - 1)
factorial 3โงจ6

๐Exercise: Write your own Unison function

Write a function which, when given a list, removes every other element from the list. So,["a", "b", "c", "d"]becomes["a", "c"].The function should work on a list of any type.

removeEveryOther : [a] -> [a]
removeEveryOther as = base.todo "Implement here"

Some tests to validate this function are copied below, but they're also available under the ex5.tests namespace.

test> test1 = check(removeEveryOther ["a","b","c","d","e"] test.=== ["a", "c", "e"])
test> test2 = check(removeEveryOther [1] test.=== [1])
test> test3 = check(removeEveryOther [] test.=== [])
โจHint
โจHint
Check outindexedfor a simple way to pair each element in the list with its index.
โจHint
โจHint
Unison's modulo function isNat.mod.
removeEveryOther : [a] -> [a]
removeEveryOther : [a] -> [a]
List.map (tup -> at1 tup) tups