Is it possible to iterate through an array using pattering matching just like we do with lists in F#? I tried something like this:
type Alphabet = A | B
let rec calc (l: Alphabet []) = match l with
|l when l.[0] = A -> 5+(calc l.[1..])
|l when l.[0] = B -> 10+(calc l.[1..])
|l when l = [||] -> 0
calc [|A;A;B|]
The problem seems to be that the loop goes on and results a stackoverflow. Is it possible to do so?
I think you are trying to do this:
let toInteger = function
| A -> 5
| B -> 10
[|A; A; B|] |> Array.sumBy toInteger
In pattern matching, you can use an array pattern: for example, [|a; b; c|] matches against a three-element array. But there is no :: operator for arrays, so it's cumbersome to use an array the way you'd use a list. This is because you can't get the array's tail as a new array without copying it.
There are a number of issues with the question's code:
It crashes due to going out of bounds of the array. This is because you are not verifying that the .[1..] slice exists.
It is not tail recursive. This may be the reason you're seeing a stack overflow on long lists.
Two features are mixed into one function, making it complicated to read: the conversion to integer and the summation.
The compiler cannot verify that the pattern match covers all cases, so it issues a warning.
As hinted before, the copying of arrays is costly. This algorithm has O(n^2) in the length of the array, making it extremely expensive for long arrays. Unlike Array.sumBy or a tail-recursive function indexing into the array, which don't have to copy the array at all.
The heart of the issue here is the difference between arrays and singly linked immutable lists. Arrays are suited for iterating over them by increasing an index (which Array.sumBy does internally), while lists allow to treat their tail as an independent list without any copying (which List.sumBy does internally). It's usually best to use each data structure the way it is intended to be used.
Related
Right now I have a few instances like this:
let doIt someList =
if someList |> List.truncate 2 |> List.length >= 2 then
someList[0] + someList[1]
else
0
I need to grab the top 2 elements of a list quite often to see changes, but in some cases I don't have enough elements and I need to make sure there are at least 2.
The best way I've found so far is to truncate the list before getting its length, but this creates allocations for no reason.
Is there a better method?
I think I would suggest pattern matching in this case:
let doIt someList =
match someList with
| a :: b :: _ -> a + b
| _ -> 0
Here, a and b are the ints in the list, while _ represents a discarded of list int. This way you don't have to pull the first two elements out of the list with an index, as they are already available as a and b. The last case of the match catches any pattern that was not matched earlier, such as cases with zero, one or three-or-more elements.
This should be a cheap operation, as F# lists are implemented as a singly linked list. So [a;b;c;d] would be represented as a::(b::(c::(d::[]))). a and b are matched, while the rest (c::(d::[])) is left untouched (and is put in the _ slot). It does not need to create a new list to do so.
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.
I'd like to get more comfortable with functional programming, and the first educational task I've set myself is converting a program that computes audio frequencies from C# to F#. The meat of the original application is a big "for" loop that selects a subset of the values in a large array; which values are taken depends on the last accepted value and a ranked list of the values seen since then. There are a few variables that persist between iterations to track progress toward determining the next value.
My first attempt at making this loop more "functional" involved a tail-recursive function whose arguments included the array, the result set so far, the ranked list of values recently seen, and a few other items that need to persist between executions. This seems clunky, and I don't feel like I've gained anything by turning everything that used to be a variable into a parameter on this recursive function.
How would a functional programming master approach this kind of task? Is this an exceptional situation in which a "pure" functional approach doesn't quite fit, and am I wrong for eschewing mutable variables just because I feel they reduce the "purity" of my function? Maybe they don't make it less pure since they only exist inside that function's scope. I don't have a feel for that yet.
Here's an attempted distillation of the code, with some "let" statements and the actual components of state removed ("temp" is the intermediate result array that needs to be processed):
let fif (_,_,_,_,fif) = fif
temp
|> Array.fold (fun (a, b, c, tentativeNextVals, acc) curVal ->
if (hasProperty curVal c) then
// do not consider current value
(a, b, c, Seq.empty, acc)
else
if (hasOtherProperty curVal b) then
// add current value to tentative list
(a, b, c, tentativeNextVals.Concat [curVal], acc)
else
// accept a new value
let newAcceptedVal = chooseNextVal (tentativeNextVals.Concat [curVal])
(newC, newB, newC, Seq.empty, acc.Concat [newAcceptedVal])
) (0,0,0,Seq.empty,Seq.empty)
|> fif
Something like this using fold?
let filter list =
List.fold (fun statevar element -> if condition statevar then statevar else element) initialvalue list
Try using Seq.skip and Seq.take:
let subset (min, max) seq =
seq
|> Seq.skip (min)
|> Seq.take (max - min)
This function will accept arrays but return a sequence, so you can convert it back using Array.ofSeq.
PS: If your goal is to keep your program functional, the most important rule is this: avoid mutability as much as you can. This means that you probably shouldn't be using arrays; use lists which are immutable. If you're using an array for it's fast random access, go for it; just be sure to never set indices.
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
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