I need a function that finds the minimum element of a list implementing the List.fold
module. I know I can use List.min but for this exercise I need it to be List.fold. So far I have:
let findMin list min = function
| [ ] -> min
| head::tail -> list |> List.fold( fun acc -> min) //missing conditional inside fold to determine min
I'm not used to functional programming, normally in java I'd do something like this:
public int getMin (){
int min = head.data;
Node curr = head.next;
while (! ( curr == NULL ) ){
if ( curr.data < min)
min = curr.data;
curr = curr.next;
}
return min;
}
But since F# works with immutable constants I can't reassign min. I've found examples of fold used to count or sum elements in a list but none that find a minimum or maximum element. I'm having trouble specifically with the conditional logic inside of the module, if anyone can help me I'd greatly appreciate it. Thank you in advance.
You don't need to deal with the case where the input list is empty because List.fold
returns the initial value in that case. Normally we pass System.Int32.MaxValue
as the initial value.
Here is long-version code:
let min a b = if a < b then a else b
let minOfList initialValue theList =
theList
|> List.fold
(fun currentMin x ->
let newMin = min currentMin x
newMin)
initialValue
let result = minOfList System.Int32.MaxValue [34; -1; 21; 99]
printfn "%d" result // -1
And short-version code:
let min a b = if a < b then a else b
let minOfList = List.fold min
let result = minOfList System.Int32.MaxValue [34; -1; 21; 99]
printfn "%d" result // -1
The concept of fold is simple: you iterate a function called the folder
function over a list. In each call the folder
function receives an element from the list and a state and it returns an updated state.
That is very similar to your imperative code: you are iterating over a list, receiving an element from the list and the old value of variable min
and after each iteration you have a new value of min
. The difference with imperative programming is the folder
function does not change the state, instead it receives one an returns another one, you can imagine if you like that List.fold
changes a variable internally.
The signature of fold is:
List.fold :
folder: 'State -> 'T -> 'State ->
state : 'State ->
list : 'T list
-> 'State
the first parameter is a folder function, the second is an initial state and the third is the list of elements. The result is going to be the last state.
So your folder
function should look something like this:
let folder min currData = ...
and your minimum
function should look like this:
let minimum ls =
ls
|> List.fold folder initial
and you call it like this:
minimum [ 5 ; 3 ; 8]
|> printfn "%A" // outputs: 3
There are some questions left about how to deal with the initial value and what happens if the list is empty. But I will leave those to you.
Hope this helps.
You can use the accumulator as the value that you would normally assign the minimum value to.
For each item of the array, fold feeds the accumulator and the current item to a given function. Whatever is returned by that function becomes the new accumulator value.
Using the built-in min
function you can write
let findMin list = List.fold min System.Int32.MaxValue list
min
is the function being applied to each item and the accumulator
System.Int32.MaxValue
is the original value of the accumulator, the seed
You could also use List.reduce
which is the same thing but it uses the first element of the list as a seed.
let findMin list = List.reduce min list
Ideally you would wrap this in something that handles the empty array case because fold
will return the seed value and reduce
will raise an exception.
Thank you to all for your help, to clear up some concepts. This is the final running snippet, the input validation is done in the main function.
// this is the folder function List.fold calls, receives the current min and item
let folder a b = if a < b then a else b
// recieves a list and returns the minimum using the List.fold module
let fold list = List.fold (fun acc elem -> folder acc elem) (List.head list) list
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.