How would I implement a get Max element function in F#? - f#

I am pretty new to F# and having trouble with some basic functions.
I am given a list:
let list1 = [1;2;3;4;5;6;7]
How would I create a getMax function that recursively iterates through list1 and finds the largest element?
What I am most confused about is what I would be returning and how I would iterate through the list.

Analogous to how, in an imperative language, you would loop through each item and store the maximum value in a variable, we write a tail-recursive function which will be translated by the compiler into a loop.
let getMax list =
let rec loop current list =
match list with
| [] -> current
| head::tail -> loop (if head > current then head else current) tail
loop (List.head list) list
This is verbose, but it's a good starting point.
Of course there's always List.max and List.maxBy, but understanding the analogue of a loop is an essential part of it.

Related

Compare values in a list

Trying to conceptualize how I would compare several values in a list to find the largest value, without using mutable variables.
For example in an imperative language I could simply store a max variable that gets updated every time the iteration finds a larger value in the list. Like such:
max = 0;
for i in list
if i > max
max = i
Now, in functional programming if i had a list, for example [1; 2; 3]
How would I get around the issue of using a max variable?
The easy answer would be to use let maxValue = List.max theList.
If you were wanting to 'roll your own' without using an explicitly mutable variable, the obvious way is to use a recursive function. Personally, I would define it like so:
let listMax theList =
let rec maxHelper remainingList maxSoFar =
match remainingList with
| [] -> maxSoFar
| h :: t ->
if h > maxSoFar then
maxHelper t h
else
maxHelper t maxSoFar
maxHelper theList (List.head theList)
Note that this implementation as presented would throw an exception with an empty input list (also, I haven't actually tested this, so there might be a slight error in there). The reason I have done it this way is that it uses tail recursion, which should mean it's roughly as efficient as a mutable solution, but keeps the complexity of the exposed function signature to the bare minimum.
Alternatively, this could also be done fairly easily with a List.fold call. E.g.
List.fold (fun (nextElem, maxSoFar) ->
if nextElem > maxSoFar then nextElem else maxSoFar) (List.head theList) theList
Same proviso about not having tested it applies to this too.
In both of the presented cases, this could be made more generic to apply to any binary operation that returns a boolean, by using another parameter that is a function which carries out said operation. E.g.
List.fold (fun (nextElem, maxSoFar) ->
if comparatorFunction nextElem maxSoFar then nextElem else maxSoFar)
(List.head theList) theList

F# print all element from the list one by one using recursion

Imagine that I have function printList that takes list as an argument and prints all the elements in the list one by one in a new row followed by the position in the list also while having space between them.
E.G
1: 4
2: 9
3: 12
How can I implement this in F# using recursion without any built-in features ?
I assume it might look something like this, but I've problems with int, unit types.
let rec printList l = function
match l with
| [] -> 0
| head::tail -> // something
There are two advices I can give you so you can implement the printList function:
you will have to make printList a non-recursive function and define a local recursive helper function in order to keep track of the index of the value.
all branches of your match expression must return the same type and here what you want is the unit type.
In case you are still stuck, I provide the solution below.
Solution
let printList list =
let rec helper index list =
match list with
| [] -> ()
| head :: tail ->
printfn "%d: %A" index head
helper (index + 1) tail
helper 1 list

F# on List of Elements

I am trying to write a F# function that finds the biggest value. I am new to F# and am confused as to how to implement this with the correct type and recursion.
Any help would be greatly appreciated along with an explanation of how it works, I really need to understand how it works so I can attempt to create other F# functions. Thanks!
When creating recursive functions, start thinking about the corner cases. Your helper function takes a list and a "maximum so far". Corner cases: What if your list is empty? What if you only have a 1 element list, or focus on the first element? That directly translates into a match statement:
let rec helper (l, m) =
match l, m with
| [], m -> m
| (l1 :: rest), m ->
let max1 = if l1 > m then l1 else m
helper(rest, max1)
I'll leave the wrapper findMax open, but clearly you can solve that using the same thinking: What if you get an empty list? (scream!) What if you get a list with elements (the first element is your maximum so far, feed the rest of the list into your helper)
And of course you could put it all into one function. I've chosen this rather roundabout helper because your template code was shaped in that way.
The first thing to do is to start thinking recursively and/or mathematically. In most general vague terms, it should look like "The result of my function is..." - then try to actually put into words what the result should be.
Applying to your particular problem, I would phrase it like this:
when given a list of one element, the result of findMax is that element.
when given a list of more than one element, the result of findMax is the maximum of the lists's head and the maximum element of its tail.
This thinking can be translated into F# almost word for word:
let rec findMax list =
match list with
| [x] -> x
| head::tail -> max head (findMax tail)
where:
let max a b = if a > b then a else b
Note, however, that this function is incomplete: it doesn't specify what the result should be when given an empty list. I will leave this as an exercise for the reader.

Comparing values in loop inside function

I want to make a function that takes an integer list as argument and compares every value and returns the largest value. In C# I would simply iterate through every value in the list, save the largest to a variable and return it, I'm hoping F# works similarly but the syntax is kinda iffy for me, here's what my code looks like. Also max2 is a function that compares 2 values and returns the largest.
let max_list list =
let a = 0 : int
match list with
| head :: tail -> (for i in list do a = max2 i a) a
| [] -> failwith "sry";;
You could use mutable variable and write the code using for loop, just like in C#. However, if you're doing this to learn F# and functional concepts, then it's good idea to use recursion.
In this case, recursive function is a bit longer, but it demonstrates the key concepts including pattern matching - so learning the tricks is something that will be useful when writing more complicated F# code.
The key idea is to write a function that takes the largest value found so far and calls itself recursively until it reaches the end of the list.
let max_list list =
// Inner recursive function that takes the largest value found so far
// and a list to be processed (if it is empty, it returns 'maxSoFar')
let rec loop maxSoFar list =
match list with
// If the head value is greater than what we found so far, use it as new greater
| head::tail when head > maxSoFar -> loop head tail
// If the head is smaller, use the previous maxSoFar value
| _::tail -> loop maxSoFar tail
// At the end, just return the largest value found so far
| [] -> maxSoFar
// Start with head as the greatest and tail as the rest to be processed
// (fails for empty list - but you could match here to give better error)
loop (List.head list) (List.tail list)
As a final note, this will be slow because it uses generic comparison (via an interface). You can make the function faster using let inline max_list list = (...). That way, the code will use native comparison instruction when used with primitive types like int (this is really a special case - the problem only really happens with generic comparison)
Also know that you can write a nice one-liner using reduce:
let max_list list = List.reduce (fun max x -> if x > max then x else max)
If your intention is to be able to find the maximum value of items in a list where the value of the items is found by the function max2 then this approach works:
let findMax list =
list
|> List.map (fun i -> i, max2 i)
|> List.maxBy snd
|> fst

having trouble using F# functions

I am new to F# and trying to learn how to use recursive function in F#. I am trying to play around with creating my own function and am having trouble getting it to work. What I have managed to do so far is get 10 random numbers and print them out. Both of those pieces of code I found online. I want to use the sort function(eventually it will be a sort function, but I am not asking for that) and am having trouble getting it to work. I put a // by where I think I am having trouble. I am not sure what this function will do, but as I wrote before I am just trying to play around with it
let randomNumberList count =
let rnd = System.Random()
List.init count (fun numbers -> rnd.Next (1, 1000))
let rec printList listx =
match listx with
| head :: tail -> printf "%d " head; printList tail
| [] -> printfn ""
let nonSortedList = randomNumberList 10
printList nonSortedList
let rec sort list =
match list with
| head :: tail -> sort tail
| [] -> 0
sort nonSortedList//I want to send the norSorted list into the sort function
printList nonSortedList//print out results after putting it into the sort function
You aren't assigning the results of sort to anything.
As F# is (largely) a functional language, it strongly encourages you to use immutable data structures. That means your data never changes, it is just passed to functions which use the data to create new representations of that data.
So your sort function is not changing the order of the list, rather it should return a new list that represents the ordered representation of the passed in list.
As F# expects this behaviour, if you don't do anything with the results F# is clever enough to know that you are probably doing something stupid.
So you should go :
let orderedList = sort nonSortedList
printList orderedList
If you really want to ignore the results - which sometimes you do, if your method has side effects and you are just calling it for its side effects - you can pass the results to ignore
sort nonSortedList |> ignore

Resources