Comparing values in loop inside function - f#

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

Related

How would I implement a get Max element function in 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.

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

Noob question about F# function parameter where the parameter is a list

I'm trying to play around with creating functions in F#, In the image below, I'm trying to create a function that takes a list of floats and sum the values in the list. I don't know how to pass a list as parameter in a function so I tried this to get the head of a list but the code doesn't work:
let sumlist l=
printf "%f" l.Head
Then I see some people does:
let sumlist l:float=
match l with
| [] -> 0.0
| e::li -> e + sumlist li
So is l:float the way you pass a list to a function? so like l:string would be a list of string?
But I saw list l has l.Head function to return the first element in the list(As it seems that we can't access arbitrary elements in the list like an array) but
let sumlist l:float=
printfn "%f" l.Head
gives type mismatch error.
I also don't understand the recursive code provided, I don't understand this line
| e::li -> e + sumlist li
What is ::? and Li?
Thank you for clarifying this for me!
So your first example doesn't return anything and that's because you're calling printfn which prints to the console instead of returning your types. e :: li here represents a list where e is the head and li is the rest of the list. The :: here lets the compiler know that you want to deconstruct the list.
//fully annotated
let s (l: float list) :float =
l.Head
//here the types can be inferred without any annotation
let rec sumlist l =
match l with
| [] -> 0.0
| e::li -> e + sumlist li
s [0.7]
//returns 0.7
sumlist [0.4;0.5;0.6]
//returns 1.5
In my first example if you try and remove the type annotations you'll notice that you get an error. This is because l.Head's type is ambiguous otherwise did you call l.Head on a list of strings, floats? In the sumlist function I provided you can see that I didn't need to annotate, and this is because I'm adding them up and that constrains the types.
Personally when starting I highly recommend always annotating the types. (l : float list) or (l: list<float>) is a way to say my input is a list of floats, and :float at the end how we say the return type is a float. You'll notice I put a rec keyword on our recursive function, it's better to explicitly declare whenever you make a recursive function.
Syntax questions
So is l:float the way you pass a list to a function?
No. Most of the time the compiler can figure out that you are passing a list without annotating the parameter as a list, but when it doesn't, you annotate is
l : 'a list // where 'a is generic type
// OR
l : float list // where type is specified as float
What is ::? and Li?
When pattern matching a list, [] matches to empty list, which here is used as the recursion end criteria. The other match separates head (e) from the rest of the list aka tail (li). If there is only one item in list, then li evaluates as [].
Additional note for your recursive code: You are missing the recursion keyword rec eg.
let rec sumlist ...
Recursive function implementation
The easiest way would be to use the sum function of List eg.
[0.4; 0.5; 0.6] |> List.sum // Returns 1.5
But, if you want to create this function yourself, consider using tail-recursion for better performance and to avoid stack overflow with bigger input lists.
let sumlist (values : float list) =
let rec sum (acc : float) (remaining : float list) =
match remaining with
| [] -> acc
| head :: tail -> sum (acc + head) tail
sum 0. values
Which is called
[0.4; 0.5; 0.6] |> sumlist // Returns 1.5
The difference here to a normal recursion is that each recursion calculates its own values and is not dependent on other recursions yet to come to finish its calculations.

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

F# sort using head::tail

I am trying to write a recursive function that uses head::tail. I understand that head in the first element of the list and tail is all other elements in the list. I also understand how recursions works. What I am wondering is how to go about sorting the elements in the list. Is there a way to compare the head to every element in the tail then choose the smallest element? My background in C++ and I am not allowed to use the List.sort(). Any idea of how to go about it? I have looked at the tutorials on the msdn site and still have had no luck
Here is recursive list-based implementation of quicksort algorithm in F#
let rec quicksort list =
match list with
| [] -> []
| h::t ->
let lesser = List.filter ((>) h) t
let greater = List.filter ((<=) h) t
(quicksort lesser) #[h] #(quicksort greater)
You need to decide a sorting methodology before worrying about the data structure used. If you were to do, say, insertion sort, you would likely want to start from the end of the list and insert an item at each recursion level, being careful how you handle the insertion itself.
Technically at any particular level you only have access to one data element, however you can pass a particular data element as a parameter to preserve it. For instance here is the inserting part of an insertion sort algorithm, it assumes the list is sorted.
let rec insert i l =
match l with
| [] -> [i]
| h::t -> if h > i then
i::l
else
h::(insert i t)
Note how I now have access to two elements, the cached one and the remainder. Another variation would be a merge sort where you had two sorted lists and therefore two items to work with any particular iteration.
Daniel's commented answer mentions a particular implementation (quicksort) if you are interested.
Finally list's aren't optimal for sorting algorithms due to their rigid structure, and the number of allocations required. Given that all known sorting algorithms are > O(n) complexity, you can translate you list to and from an array in order to improve performance without hurting your asymptotic performance.
EDIT:
Note that above isn't in tail recursive format, you would need to do something like this:
let insert i l =
let rec insert i l acc =
match l with
| [] -> List.foldBack (fun e a -> e :: a) acc [i]
| h::t -> if h > i then
List.foldBack (fun e a -> e :: a) acc i::l
else
insert i l (i::acc)
insert i l []
I don't remember offhand the best way to reverse a list so went with an example from https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/lists

Resources