I'm new to F# and have been implementing simple algorithms to learn the language constructs. I implemented the bisection method using if/else and then wanted to learn how to do it using matching.
if fc = 0.0 then printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
else if ((b - a) * 0.5) < eps then printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
else if new_count = n then printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
else if fc * fa < 0.0 then bisect a c new_count
else if fc * fb < 0.0 then bisect c b new_count
I found that using match a, b, fa, fb, fc would cause type errors, where if I took just a single parameter I could essentially ignore the parameter and check my conditions. What is the idiomatic F#/Functional way to use matching for this? Or should I just stick to if/else?
match a with
| a when fc = 0.0 -> printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
| a when ((b - a) * 0.5) < eps -> printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
| a when new_count = n -> printfn "%i/%i - f(%f) = %f, f(%f) = %f, f(%f) = %f" new_count n a fa b fb c fc
| a when fc * fa < 0.0 -> bisect a c new_count
| a when fc * fb < 0.0 -> bisect c b new_count
Your conditions all deal with disparate things, unrelated to each other, so the string of ifs is just fine. The only thing I'd recommend is using elif instead of else if.
match should be understood along the lines of "given this thing that can be of different flavors, here's how to handle those flavors". One particular strength of match is that the compiler will figure out, and tell you, if you missed any of the "flavors". In particular, the code you gave in your question should produce a compiler warning, complaining that "Incomplete pattern matches on this expression". Think about it: what would be the result of that expression when none of the cases match?
With ifs, this will also be the case. For example, this doesn't compile:
let x = if a < 5 then 7
Why? Because the compiler knows what the result should be when a < 5 (i.e. it should be 7), but what should it be otherwise? The compiler can't decide for you, so it will generate an error.
This, on the other hand, would compile:
let x = if a < 5 then 7 else 8
But in your particular case, the compiler lets you get away with this, because all your branches return a unit (why? because printf returns unit, and all others are recursive). In other words, the following will compile:
let x = if a < 5 then ()
And the following:
let x = if a < 5 then printf "boo!"
The compiler lets you get away with this, because unit is special: it can only ever have one value (namely, ()), so the compiler can decide for you what the result of the expression would be when the condition isn't true.
One practical upshot of this would be that, if you didn't think about your conditions very carefuly, it could conceivably happen so that none of your conditions are true, and so the whole thing will return unit and not print anything. I can't say if that could happen in your particular case, because I don't see the whole function definition.
Sometimes, as Fyodor Soikin correctly explains, a series of if, else if, else expressions is the best option, although I'd use elif instead of else if.
What sometimes make sense is to compute some of the values before, and put them into a data structure you can match on - typically a tuple.
Using a simplified version of the above question, imagine that you only need to check the first two cases, you could do it like this:
match fc = 0., ((b - a) * 0.5) < eps with
| true, _ -> "fc is 0"
| _, true -> "((b - a) * 0.5) is less than eps"
| _ -> "etc."
Notice the comma after fc = 0., which makes the match expression into a tuple - more specifically a bool * bool.
This has the disadvantage that it's inefficient, because you'd always be evaluating the expression ((b - a) * 0.5) < eps, even if fc = 0. evaluates to true.
Still, evaluating a simple expression like ((b - a) * 0.5) < eps will be so fast that you probably wouldn't be able to measure it, so if you think this way of expressing the algorithm is more readable, you could decide to trade off that small inefficiency for better readability.
In this case, though, I don't think it's more readable, so I'd still go with a series of if, elif, else expressions.
Here's an example where pre-computing values and putting them into a tuple makes more sense:
match number % 3, number % 5 with
| 0, 0 -> "FizzBuzz"
| _, 0 -> "Buzz"
| 0, _ -> "Fizz"
| _ -> number.ToString()
This is a common implementation of the FizzBuzz kata. Here it make sense because both modulo numbers are needed for the first match, so there's no inefficiency, and the code is quite readable as well.
The point about inefficiency above is true for F# because F# is eagerly evaluated. In Haskell, on the other hand, expressions are lazily evaluated, so there you'd be able to do the following without loss of efficiency:
case (fc == 0.0, ((b - a) * 0.5) < eps) of
(True, _) -> "fc is 0"
(_, True) -> "((b - a) * 0.5) is less than eps"
_ -> "etc."
The second expression in the tuple would only be evaluated if necessary, so if the first case ((True, _)) is matched, there'd be no need to evaluate the second expression.
Related
Given a list int from -273 to 5526, I want to print the closest integer to zero. In case of you have equality (n and -n) we should take n.
let temps = // this contains => 1 -2 -8 4 5
let (|Greater|_|) a b = if a > b then Some() else None
let (|Smaller|_|) a b = if a < b then Some() else None
let compareTemperatures a b =
let distanceA = abs a
let distanceB = abs b
match distanceA with
| Greater distanceB -> b
| Smaller distanceB -> a
| _ -> abs a
printfn "%i" (temps |> Seq.reduce compareTemperatures)
And that returns -8 instead of 1. It seems correct to me and I can't find the bug but I'm new to F# so I might have make a mistake anywhere and can't see it :(
Thanks in advance
I think you got the comparison the wrong way round - when you write:
match distanceA with
| Greater distanceB -> b
| Smaller distanceB -> a
Then distanceA gets passed as the second parameter to Greater and so you are returning b (in the first case) in case when b is further away from zero. The following will make it work:
match distanceA with
| Greater distanceB -> a
| Smaller distanceB -> b
That said, using active patterns for this just makes the code unnecessarily complicated (and makes it easy to introduce bugs like this one). The following does the same thing and it is easy to understand and also a lot simpler:
let compareTemperatures a b =
if abs a > abs b then b else a
temps |> Seq.reduce compareTemperatures
I think the lesson here is that pattern matching works really well for things like algebraic data types and option values, but it is not that useful for simple numerical comparisons where if works fine!
So you want to compare the values, using first the absolute value, then the sign. Here's my one-liner:
temps |> Seq.minBy (fun x -> abs x, -sign x)
Test case (prints 2):
let li = [-2; 2; -2; 3; -5]
li |> Seq.minBy (fun x -> abs x, -sign x) |> printfn "%d"
This should have been a comment to Thomas' answer, but I'm too stupid for the mobile app...
How about if abs (2*a-1) > abs (2*b) then b else a?
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)
let rec f n =
match n with
| 0 | 1 | 2 -> 1
| _ -> f (n - 2) + f (n - 3)
Without CPS or Memoization, how could it be made tail recursive?
let f n = Seq.unfold (fun (x, y, z) -> Some(x, (y, z, x + y))) (1I, 1I, 1I)
|> Seq.nth n
Or even nicer:
let lambda (x, y, z) = x, (y, z, x + y)
let combinator = Seq.unfold (lambda >> Some) (1I, 1I, 1I)
let f n = combinator |> Seq.nth n
To get what's going on here, refer this snippet. It defines Fibonacci algorithm, and yours is very similar.
UPD There are three components here:
The lambda which gets i-th element;
The combinator which runs recursion over i; and
The wrapper that initiates the whole run and then picks up the value (from a triple, like in #Tomas' code).
You have asked for a tail-recursive code, and there are actually two ways for that: make your own combinator, like #Tomas did, or utilize the existing one, Seq.unfold, which is certainly tail-recursive. I preferred the second approach as I can split the entire code into a group of let statements.
The solution by #bytebuster is nice, but he does not explain how he created it, so it will only help if you're solving this specific problem. By the way, your formula looks a bit like Fibonacci (but not quite) which can be calculated analytically without any looping (even without looping hidden in Seq.unfold).
You started with the following function:
let rec f0 n =
match n with
| 0 | 1 | 2 -> 1
| _ -> f0 (n - 2) + f0 (n - 3)
The function calls f0 for arguments n - 2 and n - 3, so we need to know these values. The trick is to use dynamic programming (which can be done using memoization), but since you did not want to use memoization, we can write that by hand.
We can write f1 n which returns a three-element tuple with the current and two past values values of f0. This means f1 n = (f0 (n - 2), f0 (n - 1), f0 n):
let rec f1 n =
match n with
| 0 -> (0, 0, 1)
| 1 -> (0, 1, 1)
| 2 -> (1, 1, 1)
| _ ->
// Here we call `f1 (n - 1)` so we get values
// f0 (n - 3), f0 (n - 2), f0 (n - 1)
let fm3, fm2, fm1 = (f1 (n - 1))
(fm2, fm1, fm2 + fm3)
This function is not tail recurisve, but it only calls itself recursively once, which means that we can use the accumulator parameter pattern:
let f2 n =
let rec loop (fm3, fm2, fm1) n =
match n with
| 2 -> (fm3, fm2, fm1)
| _ -> loop (fm2, fm1, fm2 + fm3) (n - 1)
match n with
| 0 -> (0, 0, 1)
| 1 -> (0, 1, 1)
| n -> loop (1, 1, 1) n
We need to handle arguments 0 and 1 specially in the body of fc. For any other input, we start with initial three values (that is (f0 0, f0 1, f0 2) = (1, 1, 1)) and then loop n-times performing the given recursive step until we reach 2. The recursive loop function is what #bytebuster's solution implements using Seq.unfold.
So, there is a tail-recursive version of your function, but only because we could simply keep the past three values in a tuple. In general, this might not be possible if the code that calculates which previous values you need does something more complicated.
Better even than a tail recursive approach, you can take advantage of matrix multiplication to reduce any recurrence like that to a solution that uses O(log n) operations. I leave the proof of correctness as an exercise for the reader.
module NumericLiteralG =
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
// these operators keep the inferred types from getting out of hand
let inline ( + ) (x:^a) (y:^a) : ^a = x + y
let inline ( * ) (x:^a) (y:^a) : ^a = x * y
let inline dot (a,b,c) (d,e,f) = a*d+b*e+c*f
let trans ((a,b,c),(d,e,f),(g,h,i)) = (a,d,g),(b,e,h),(c,f,i)
let map f (x,y,z) = f x, f y, f z
type 'a triple = 'a * 'a * 'a
// 3x3 matrix type
type 'a Mat3 = Mat3 of 'a triple triple with
static member inline ( * )(Mat3 M, Mat3 N) =
let N' = trans N
map (fun x -> map (dot x) N') M
|> Mat3
static member inline get_One() = Mat3((1G,0G,0G),(0G,1G,0G),(0G,0G,1G))
static member (/)(Mat3 M, Mat3 N) = failwith "Needed for pown, but not supported"
let inline f n =
// use pown to get O(log n) time
let (Mat3((a,b,c),(_,_,_),(_,_,_))) = pown (Mat3 ((0G,1G,0G),(0G,0G,1G),(1G,1G,0G))) n
a + b + c
// this will take a while...
let bigResult : bigint = f 1000000
I am playing with a toy problem (Convex hull identification) and needed lexicographic sorting twice already. One of the cases was given a list of type Point = { X: float; Y: float }, I would like to sort by X coordinate, and in case of equality, by Y coordinate.
I ended up writing the following:
let rec lexiCompare comparers a b =
match comparers with
[ ] -> 0
| head :: tail ->
if not (head a b = 0) then head a b else
lexiCompare tail a b
let xComparer p1 p2 =
if p1.X > p2.X then 1 else
if p1.X < p2.X then -1 else
0
let yComparer p1 p2 =
if p1.Y > p2.Y then 1 else
if p1.Y < p2.Y then -1 else
0
let coordCompare =
lexiCompare [ yComparer; xComparer ]
Which allows me to do
let lowest (points: Point list) =
List.sortWith coordCompare points
|> List.head
So far, so good. However, this feels a bit heavy-handed. I have to create specific comparers returning -1, 0 or 1, and so far I can't see a straightforward way to use this in cases like List.minBy. Ideally, I would like to do something along the lines of providing a list of functions that can be compared (like [(fun p -> p.X); (fun p -> p.Y)]) and do something like lexicographic min of a list of items supporting that list of functions.
Is there a way to achieve this in F#? Or am I thinking about this incorrectly?
Is there a way to achieve this in F#? Or am I thinking about this incorrectly?
F# does this for you automatically when you define a record type like yours:
> type Point = { X: float; Y: float };;
type Point =
{X: float;
Y: float;}
You can immediately start comparing values. For example, defining a 3-element list of points and sorting it into lexicographic order using the built-in List.sort:
> [ { X = 2.0; Y = 3.0 }
{ X = 2.0; Y = 2.0 }
{ X = 1.0; Y = 3.0 } ]
|> List.sort;;
val it : Point list = [{X = 1.0;
Y = 3.0;}; {X = 2.0;
Y = 2.0;}; {X = 2.0;
Y = 3.0;}]
Note that the results were sorted first by X and then by Y.
You can compare two values of any comparable type using the built-in compare function.
If you want to use a custom ordering then you have two options. If you want to do all of your operations using your custom total order then it belongs in the type definition as an implementation of IComparable and friends. If you want to use a custom ordering for a few operations then you can use higher-order functions like List.sortBy and List.sortWith. For example, List.sortBy (fun p -> p.Y, p.X) will sort by Y and then X because F# generates the lexicographic comparison over 2-tuples for you (!).
This is one of the big advantages of F#.
Well, to start with, you can rely on F#'s built-in compare function:
let xComparer p1 p2 = compare p1.X p2.X
let yComparer p1 p2 = compare p1.Y p2.Y
Alternatively, you can clearly abstract this a bit if desired:
let compareWith f a b = compare (f a) (f b)
let xComparer = compareWith (fun p -> p.X)
let yComparer = compareWith (fun p -> p.Y)
Or, as you note, you could build this approach directly into the list handling function:
let rec lexiCompareWith l a b =
match l with
| [] -> 0
| f::fs ->
match compare (f a) (f b) with
| 0 -> lexiCompareWith fs a b
| n -> n
One important limitation here is that since you're putting them into a list, the functions must all have identical return types. This isn't a problem in your Point example (since both functions have type Point -> float), but it would prevent you from sorting two Person objects by name and then age (since the first projection would have type Person -> string but the second would have type Person -> int).
I don't think I understand your question correctly, but doesn't the following code work fine?
let lowest (points : Point list) = List.sort points |> List.head
It seems that F# performs implicit comparison on record data types. And my little experiment indicates that the comparison happens to be lexicographic. But I could not find any evidence to support that result.
So I'm not yet sure F# compares records lexicographically. I can still write in the following manner using tuple instead:
let lowest (points : Point list) =
let tuple = List.map (fun pt -> (pt.X, pt.Y)) points |> List.sort |> List.head
{ X = fst tuple; Y = snd tuple }
I hope this post could help.
I am trying to learn F# so I paid a visit to Project Euler and I am currently working on Problem 3.
The prime factors of 13195 are 5, 7,
13 and 29.
What is the largest prime
factor of the number 600851475143?
Some things to consider:
My first priority is to learn good functional habits.
My second priority is I would like it to be fast and efficient.
Within the following code I have marked the section this question is regarding.
let isPrime(n:int64) =
let rec check(i:int64) =
i > n / 2L or (n % i <> 0L && check(i + 1L))
check(2L)
let greatestPrimeFactor(n:int64) =
let nextPrime(prime:int64):int64 =
seq { for i = prime + 1L to System.Int64.MaxValue do if isPrime(i) then yield i }
|> Seq.skipWhile(fun v -> n % v <> 0L)
|> Seq.hd
let rec findNextPrimeFactor(number:int64, prime:int64):int64 =
if number = 1L then prime else
//************* No variable
(fun p -> findNextPrimeFactor(number / p, p))(nextPrime(prime))
//*************
//************* Variable
let p = nextPrime(prime)
findNextPrimeFactor(number / p, p)
//*************
findNextPrimeFactor(n, 2L)
Update
Based off some of the feedback I have refactored the code to be 10 times faster.
module Problem3
module private Internal =
let execute(number:int64):int64 =
let rec isPrime(value:int64, current:int64) =
current > value / 2L or (value % current <> 0L && isPrime(value, current + 1L))
let rec nextPrime(prime:int64):int64 =
if number % prime = 0L && isPrime(prime, 2L) then prime else nextPrime(prime + 1L)
let rec greatestPrimeFactor(current:int64, prime:int64):int64 =
if current = 1L then prime else nextPrime(prime + 1L) |> fun p -> greatestPrimeFactor(current / p, p)
greatestPrimeFactor(number, 2L)
let execute() = Internal.execute(600851475143L)
Update
I would like to thank everyone for there advice. This latest version is a compilation of all the advice I received.
module Problem3
module private Internal =
let largestPrimeFactor number =
let rec isPrime value current =
current > value / 2L || (value % current <> 0L && isPrime value (current + 1L))
let rec nextPrime value =
if number % value = 0L && isPrime value 2L then value else nextPrime (value + 1L)
let rec find current prime =
match current / prime with
| 1L -> prime
| current -> nextPrime (prime + 1L) |> find current
find number (nextPrime 2L)
let execute() = Internal.largestPrimeFactor 600851475143L
Functional programming becomes easier and more automatic with practice, so don't sweat it if you don't get it absolutely right on the first try.
With that in mind, let's take your sample code:
let rec findNextPrimeFactor(number:int64, prime:int64):int64 =
if number = 1L then prime else
//************* No variable
(fun p -> findNextPrimeFactor(number / p, p))(nextPrime(prime))
//*************
//************* Variable
let p = nextPrime(prime)
findNextPrimeFactor(number / p, p)
//*************
Your no variable version is just weird, don't use it. I like your version with the explicit let binding.
Another way to write it would be:
nextPrime(prime) |> fun p -> findNextPrimeFactor(number / p, p)
Its ok and occasionally useful to write it like this, but still comes across as a little weird. Most of the time, we use |> to curry values without needing to name our variables (in "pointfree" style). Try to anticipate how your function will be used, and if possible, re-write it so you can use it with the pipe operator without explicit declared variables. For example:
let rec findNextPrimeFactor number prime =
match number / prime with
| 1L -> prime
| number' -> nextPrime(prime) |> findNextPrimeFactor number'
No more named args :)
Ok, now that we have that out of the way, let's look at your isPrime function:
let isPrime(n:int64) =
let rec check(i:int64) =
i > n / 2L or (n % i <> 0L && check(i + 1L))
check(2L)
You've probably heard to use recursion instead of loops, and that much is right. But, wherever possible, you should abstract away recursion with folds, maps, or higher order functions. Two reasons for this:
its a little more readable, and
improperly written recursion will result in a stack overflow. For example, your function is not tail recursive, so it'll blow up on large values of n.
I'd rewrite isPrime like this:
let isPrime n = seq { 2L .. n / 2L } |> Seq.exists (fun i -> n % i = 0L) |> not
Most of the time, if you can abstract away your explicit looping, then you're just applying transformations to your input sequence until you get your results:
let maxFactor n =
seq { 2L .. n - 1L } // test inputs
|> Seq.filter isPrime // primes
|> Seq.filter (fun x -> n % x = 0L) // factors
|> Seq.max // result
We don't even have intermediate variables in this version. Coolness!
My second priority is I would like it
to be fast and efficient.
Most of the time, F# is going to be pretty comparable with C# in terms of speed, or it's going to be "fast enough". If you find your code takes a long time to execute, it probably means you're using the wrong data structure or a bad algorithm. For a concrete example, read the comments on this question.
So, the code I've written is "elegant" in the sense that its concise, gives the correct results, and doesn't rely on any trickery. Unfortunately, its not very fast. For start:
it uses trial division to create a sequence of primes, when the Sieve of Eratosthenes would be much faster. [Edit: I wrote a somewhat naive version of this sieve which didn't work for numbers larger than Int32.MaxValue, so I've removed the code.]
read Wikipedia's article on the prime counting function, it'll give you pointers on calculating the first n primes as well as estimating the upper and lower bounds for the nth prime.
[Edit: I included some code with a somewhat naive implementation of a sieve of eratosthenes. It only works for inputs less than int32.MaxValue, so it probably isn't suitable for project euler.]
Concerning "good functional habit" or rather good practice I see three minor things. Using the yield in your sequence is a little harder to read than just filter. Unnecessary type annotations in a type inferred language leads to difficult refactoring and makes the code harder to read. Don't go overboard and try to remove every type annotation though if you're finding it difficult. Lastly making a lambda function which only takes a value to use as a temp variable reduces readability.
As far as personal style goes I prefer more spaces and only using tupled arguments when the data makes sense being grouped together.
I'd write your original code like this.
let isPrime n =
let rec check i =
i > n / 2L || (n % i <> 0L && check (i + 1L))
check 2L
let greatestPrimeFactor n =
let nextPrime prime =
seq {prime + 1L .. System.Int64.MaxValue}
|> Seq.filter isPrime
|> Seq.skipWhile (fun v -> n % v <> 0L)
|> Seq.head
let rec findNextPrimeFactor number prime =
if number = 1L then
prime
else
let p = nextPrime(prime)
findNextPrimeFactor (number / p) p
findNextPrimeFactor n 2L
Your updated code is optimal for your approach. You would have to use a different algorithm like Yin Zhu answer to go faster. I wrote a test to check to see if F# makes the "check" function tail recursive and it does.
the variable p is actually a name binding, not a variable. Using name binding is not a bad style. And it is more readable. The lazy style of nextPrime is good, and it actually prime-test each number only once during the whole program.
My Solution
let problem3 =
let num = 600851475143L
let rec findMax (n:int64) (i:int64) =
if n=i || n<i then
n
elif n%i=0L then
findMax (n/i) i
else
findMax n (i+1L)
findMax num 2L
I basically divides num from 2, 3, 4.. and don't consider any prime numbers. Because if we divides all 2 from num, then we won't be able to divide it by 4,8, etc.
on this number, my solution is quicker:
> greatestPrimeFactor 600851475143L;;
Real: 00:00:01.110, CPU: 00:00:00.702, GC gen0: 1, gen1: 1, gen2: 0
val it : int64 = 6857L
>
Real: 00:00:00.001, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val problem3 : int64 = 6857L
I think that the code with the temporary binding is significantly easier to read. It's pretty unusual to create an anonymous function and then immediately apply it to a value as you do in the other case. If you really want to avoid using a temporary value, I think that the most idiomatic way to do that in F# would be to use the (|>) operator to pipe the value into the anonymous function, but I still think that this isn't quite as readable.