I'm messing around with F# and Fable, and trying to test my understanding. To do so, I tried creating a function to calculate e given a certain number of iterations. What I've come up with is
let eCalc n =
let rec internalECalc ifact sum count =
match count = n with
| true -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
Which works fine, returning 2.7182818284590455 when called with
eCalc 20
However, if I try using, what I think is, the more correct form
let eCalc n =
let rec internalECalc ifact sum count =
match count with
| n -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
I get a warning "[WARNING] This rule will never be matched (L5,10-L5,11)", and returned value of 0. (and the same thing happens if I swap 'n' and 'count' in the match statement). Is there a reason I can't use 'n' in the match statement? Is there a way around this so I can use 'n'?
Thanks
When you use a name in a match statement, you're not checking it against the value assigned to that variable the way you think you are. You are instead assigning that name. I.e.,
match someInt with
| n -> printfn "%d" n
will print the value of someInt. It's the equivalent of let n = someInt; printfn "%d" n.
What you wanted to do was use a when clause; inside a when clause, you're not pattern-matching, but doing a "standard" if check. So what you wanted was:
let eCalc n =
let rec internalECalc ifact sum count =
match count with
| cnt when cnt = n -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
Does that make sense, or do you need me to go into more detail?
P.S. In a case like this one where your match function looks like "x when (boolean condition involving x) -> case 1 | _ -> case 2", it's quite a bit more readable to use a simple if expression:
let eCalc n =
let rec internalECalc ifact sum count =
if count = n then
sum
else
internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
Related
I'm trying to reverse an integer in F#. I have the following approach:
//let the number be n
rev = 0
while(n != 0){
rev = rev * 10 + n % 10;
n /= 10;
}
// rev now contains the reverse integer of n
I'm new to F#, and I don't know the the idiomatic syntax to achieve this implementation. I don't want to reverse the number by converting it to string first. How can this implementation be done in F# in an idiomatic way?
Create a recursive inner function that you call like so.
let reverse n =
let rec revInner n rev =
match n with
| 0 -> rev
| _ -> revInner (n / 10) (rev * 10 + n % 10)
revInner n 0
reverse 43221 // -> 12234
Whenever you have imperative loops such as a while look to convert it to a recursive function. In this case you need an inner function that is recursively called. The first pattern match deals with the termination condition of the while, the second deals with the core whileexecution:
let revNum number =
let rec loop rev = function
| 0 -> rev
| fwd -> loop (rev*10 + fwd%10) (fwd/10)
loop 0 number;;
I'm trying to find the average of a list
Here's what I have so far
let rec avg aList =
match aList with
| head::tail -> head+avg(tail)
| [] -> 0
This obtains the sum. I've tried head+avg(tail)/aList.Length, but it gives me an incorrect result as I don't know exactly what that's doing
Any help would be appreciated
For an average, you'd want two things, the sum and the number of items. Using List.length would mean traversing the list again.
We can do those two things at the same time - by using a tuple.
This operation is known as folding (or sometimes aggregation). We apply the folding function, gathering our state as we traverse the list without mutating anything.
let avg aList =
let rec accumulate (sum, count) list =
match list with
| head::tail -> accumulate (sum + head, count + 1) tail
| [] -> (sum, count)
let sum, count = accumulate (0, 0) aList
let average = sum / count
average
You can generalize this using fold.
let avg aList =
let sum, count =
List.fold (fun (sum, count) current -> (sum + current, count + 1)) (0,0) aList
let average = sum / count
average
The generic math version:
let inline avg (list: 'a list) =
let rec accumulate (sum, count) list =
match list with
| head::tail -> accumulate (Checked.(+) sum head, count + 1) tail
| [] -> (sum, count)
let sum, count = accumulate (LanguagePrimitives.GenericZero<'a>, 0) list
let average = LanguagePrimitives.DivideByInt sum count
average
The simplest way of doing this is using the average high-order function from the List module. You can do this on a single line with
let myAverage = aList |> List.average
let avg aList =
let rec sum = function
| head :: tail -> head + (sum tail)
| [] -> 0.
sum aList / (aList |> List.length |> float)
let res = avg [ 2.; 4.; 6. ]
printfn "%A" res
I'm not sure this is the best way to do it tho.
I have a csv file containing daily weights as follows:
Date,Name,Weight
11-Sep-2017,Alpha,9-1
13-Sep-2017,Alpha,8-13
15-Sep-2017,Alpha,8-11
Though I can successfully import them using CsvProvider, the weight column defaults to System.DateTime.
// Weight
[<Measure>] type lb
[<Literal>]
let input = "DayWeights.csv"
type Weights = CsvProvider<input, HasHeaders=true>
let data = Weights.GetSample()
for row in data.Rows do
printfn "Output: (%A, %A, %A)" row.Date row.Name row.Weight
Is it possible to create a Unit of Measure (UoM) to define "stlb" with the option to convert to lbs on import and, if so, how?
I don't think you could represent stones-pounds as a single numeric type, and units of measure can only be used on numeric types (although there is some discussion about changing this in future). This is because some of their features only make sense with numeric operations like addition and multiplication. The units themselves are multiplied and divided:
[<Measure>] type lb
2<lb> + 2<lb> // 4<lb>
2<lb> * 2<lb> // 4<lb ^ 2>
2<lb> / 2<lb> // 1
Instead of units of measure, if you want some kind of tag to know that a given value has a type of stones-pounds, you could create a single case discriminated union:
type StonesPounds = StonesPounds of int * int
// StonesPounds -> int<lb>
let convertToLb (StonesPounds (s, p)) = (s * 14 + p) * 1<lb>
StonesPounds (1, 2) |> convertToLb // 16<lb>
The downside of this compared to units of measure is that you have to manually pack and unpack these values in code before you can use the numbers and there is a runtime cost for that too.
I resolved the automatic converting of the input weight column to System.DateTime as follows:
// http://fssnip.net/27
let lazySplit (sep:string) (str:string) =
match sep, str with
| ((null | ""), _) | (_, (null | "")) -> seq [str]
| _ ->
let n, j = str.Length, sep.Length
let rec loop p =
seq {
if p < n then
let i = match str.IndexOf(sep, p) with -1 -> n | i -> i
yield str.Substring(p, i - p)
yield! loop (i + j)
}
loop 0
let weight input =
input
|> (fun x -> lazySplit "/" x |> Seq.take 2 |> String.concat("-"))
let data = Weighings.GetSample()
for row in data.Rows do
let stlbs = weight (string row.Weight)
printfn "Output: (%A, %A, %A)" row.Date row.Name stlbs
// Output: 11-Sep-2017,"Alpha","09-01")
Thanks to one and all for your expert help and guidance.
I'm trying to create an infinite Stream in F# that contains armstrong numbers. An armstrong number is one whose cubes of its digits add up to the number. For example, 153 is an armstrong number because 1^3 + 5^3 + 3^3 = 153. so far, I have created several functions to help me do so. They are:
type 'a stream = Cons of 'a * (unit -> 'a stream);;
let rec upfrom n = Cons (n, fun() -> upfrom (n+1));;
let rec toIntArray = function
| 0 -> []
| n -> n % 10 :: toIntArray (n / 10);;
let rec makearmstrong = function
| [] -> 0
| y::ys -> (y * y * y) + makearmstrong ys;;
let checkarmstrong n = n = makearmstrong(toIntArray n);;
let rec take n (Cons(x,xsf)) =
match n with
| 0 -> []
| _ -> x :: take (n-1)(xsf());;
let rec filter p (Cons (x, xsf)) =
if p x then Cons (x, fun() -> filter p (xsf()))
else filter p (xsf());;
And finally:
let armstrongs = filter (fun n -> checkarmstrong n)(upfrom 1);;
Now, when I do take 4 armstrongs;;, (or any number less than 4) this works perfectly and gives me [1;153;370;371] but if I do take 5 armstrongs;;nothing happens, it seems like the program freezes.
I believe the issue is that there are no numbers after 407 that are the sums of their cubes (see http://oeis.org/A046197), but when your code evaluates the equivalent of take 1 (Cons(407, filter checkarmstrong (upfrom 408))) it's going to force the evaluation of the tail and filter will recurse forever, never finding a matching next element. Also note that your definition of Armstrong numbers differs from, say, Wikipedia's, which states that the power the digits are raised to should be the number of digits in the number.
I'm trying to build the nth power function in F#. (Yes, there's already Math.Pow in .Net). Here is my attempt:
let rec nthPower x n =
match n with
| 0 -> 1
| _ -> x * (nthPower x (n-1))
This works fine when n >= 0; however, I don't know how to handle the negative case: when n < 0.
Question:
How to handle the negative case? (n<0)
Is this recursive algorithm efficient? or are there any efficient ways in F#?
You can implement it like this:
let rec nthPower x n =
match n with
| 0 -> 1m
| t when t < 0 -> 1m / (nthPower x -n)
| _ -> decimal x * (nthPower x (n - 1));;
The t when t < 0 allows the pattern matching to match a range of values. I would say that the RHS of this line is self-explanatory, but let me know if it's unclear.
Regarding question #2, I don't think there's anything particularly inefficient about this approach and there's probably not a much simpler way to do it. I'm not sure what the most efficient approach is, but hopefully some mathematicians can chime in.
Edit: I have found an approach that is more efficient for exponents > ~10. It uses memoization and divide-and-conquer to compute the result in O(log n) time instead of O(n):
let rec nthPower x n =
match n with
| 0 -> 1.0
| 1 -> double x
| t when t < 0 -> 1.0 / (nthPower x -n)
| _ ->
let p = nthPower x (n / 2)
p * p * nthPower x (n % 2)