So I've written a pretty simple program in F# that should sum all of the multiples of 3 and 5 below 1000:
[1..999]
|> List.filter (fun x -> x % 3 = 0 || x % 5 = 0)
|> let total = List.sum`
However, at the very end of the program I get the following error:
Unexpected end of input in expression. Expected 'in' or other token.
I am using the lightweight syntax, so I'm not sure why F# would want me to use an 'in' statement. Any thoughts?
You probably intended to do this:
let total =
[1..999]
|> List.filter (fun x -> x % 3 = 0 || x % 5 = 0)
|> List.sum
The error message you are getting is because it expects a function after the forward pipe, you can have a let binding but as part of a function expecting at least one parameter.
Related
For example; the following line
|> Seq.filter(fun i -> i < 123)
is the same thing as
|> Seq.filter((<) 123)
Is there such a thing for the modulo operator? I'm not sure what the 2nd variant is, and can't find it referenced in the documentation either, so it makes searching somewhat difficult. So for bonus points, please tell me what this operator is called! :)
Currently using:
|> Seq.filter (fun i -> i % 2 = 0)
Looking for something like:
|> Seq.filter ((%) 2 = 0)
Your first example is incorrect in saying that fun i -> i < 123 is equal to ((<) 123). That is actually equivalent to fun i -> 123 < i. Let me explain, every operator is just a function but infix rather than prefix. As an example
let (+) x y = x + y
let add x y = x + y
let (-) a b = a - b // notice that the first argument (a) is on the left side of the operator
let subs a b = a - b
knowing this, we can then reason about % and < the same way
let (%) x y = x % y
let (<) x y = x < y
// therefore
fun i -> i < 123
// is equivalent to
fun i -> (<) i 123
// and mathematically equiv to
((>=) 123)
// same with %
fun i -> i % 2
// is equiv to
fun i -> (%) i 2
// thus cant be reduced to eliminate the lambda
Another alternative, if you're dead-set on not writing out the lambda, is to lift it into a function:
let inline isEven x = x % 2 = 0
...
|> Seq.filter isEven
Alas, you are out of luck, because for partial application to be suitable, you need to swap both arguments of the mod operator. The lambda function is way more concise when taking into account that you are applying two operators, which requires function composition.
let flip f a b = f b a
{0..9}
|> Seq.filter ((flip (%) 2) >> ((=) 0))
|> (Seq.map string >> String.concat ", ")
// val it : string = "0, 2, 4, 6, 8"
I can obtain the even numbers in a list using the lambda syntax:
[1..10] |> List.filter (fun x -> x % 2 = 0)
But I want get it with composition, like this:
[1..10] |> List.filter ((% 2) >> (= 0))
Error: stdin(7,37): error FS0010: Unexpected integer literal in expression. Expected ')' or other token.
F# does not support operator sections. You can partially apply an operator by enclosing it in parentheses, like so:
let five = (+) 2 3
let add2 = (+) 2
let alsoFive = add2 3
However, this will not allow you to partially apply the right argument of the operator. In other words, F# does not offer anything equivalent to Haskell expression (/ 2). This can be worked around for commutative operators, such as addition or multiplication, because (+ 2) === (2 +), which in F# can be expressed as ((+) 2), but not for non-commutative ones.
The best you can do is declare the section as a separate function, like this:
let mod2 x = x % 2
[1..10] |> List.filter (mod2 >> ((=) 0))
If you absolutely insist on not declaring any more functions, you could try to do with a flip:
[1..10] |> List.filter ((flip (%) 2) >> ((=) 0))
But sadly, F# standard library does not provide a flip function either, so you'd have to declare it yourself anyway:
let inline flip f a b = f b a
Personally, I would rather go for increased readability and declare an isEven function:
let isEven x = (x % 2) = 0
[1..10] |> List.filter isEven
I have been attempting the Eulers in F#* and am currently on #5. My problem is using a function that takes more than one parameter in a pipeline operation.
This function correctly returns whether the first parameter is divisible by every member of an array which is the second parameter:
let isDivisibleBy seq n =
seq
|> Seq.forall (fun x -> n % x = 0)
isDivisibleBy [|1 .. 10|] 2520 //true
However, the following statement does not work:
Seq.initInfinite
|> Seq.find isDivisibleBy [|1 .. 10|]
I get the following error:
error FS0001: The type '((int -> 'c) -> seq<'c>) -> 'd' is not compatible with the type 'seq<'a>'
*"2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"
Short answer:
You're missing parentheses and first argument of Seq.initInfinite. Correct code:
Seq.initInfininte id
|> Seq.find (isDivisibleBy [|1..10|])
Explanation
In expression Seq.find isDivisibleBy [|1 .. 10|] you're trying to call function Seq.find with two arguments, isDivisibleBy and [|1 .. 10|]. And then you're trying to use the resulting value as second argument of the pipe (|>) operator. Your code is equivalent to this (just make each call a separate step):
let a = Seq.find isDivisibleBy [|1 .. 10|]
Seq.initInfinite |> a
Which is obviously incorrect.
From the rest of your code, I infer that what you probably wanted to do was to partially apply the function isDivisibleBy to argument [|1 .. 10|], and then pass the resulting value to Seq.find, like this:
let b = isDivisibleBy [|1 .. 10|]
let a = Seq.find b
Seq.initInfinite |> a
But this still won't compile, because Seq.initInfinite takes one argument - a function mapping indexes to elements of generated sequence, - but you provide no arguments:
let b = isDivisibleBy [|1 .. 10|]
let a = Seq.find b
let c = Seq.initInfinite (fun x -> x)
c |> a
Removing intermediate lets from the above code and replacing the redundant lambda fun x -> x with id, we get the final answer:
Seq.initInfininte id
|> Seq.find (isDivisibleBy [|1..10|])
Creating a Parallel.ForEach expression of this form:
let low = max 1 (k-m)
let high = min (k-1) n
let rangesize = (high+1-low)/(PROCS*3)
Parallel.ForEach(Partitioner.Create(low, high+1, rangesize), (fun j ->
let i = k - j
if x.[i-1] = y.[j-1] then
a.[i] <- b.[i-1] + 1
else
a.[i] <- max c.[i] c.[i-1]
)) |> ignore
Causes me to receive the error: No overloads match for method 'ForEach'. However I am using the Parallel.ForEach<TSource> Method (Partitioner<TSource>, Action<TSource>) and it seems right to me. Am I missing something?
Edited: I am trying to obtain the same results as the code below (that does not use a Partitioner):
let low = max 1 (k-m)
let high = min (k-1) n
let rangesize = (high+1-low)/(PROCS*3)
let A = [| low .. high |]
Parallel.ForEach(A, fun (j:int) ->
let i = k - j
if x.[i-1] = y.[j-1] then
a.[i] <- b.[i-1] + 1
else
a.[i] <- max c.[i] c.[i-1]
) |> ignore
Are you sure that you have opened all necessary namespaces, all the values you are using (low, high and PROCS) are defined and that your code does not accidentally redefine some of the names that you're using (like Partitioner)?
I created a very simple F# script with this code and it seems to be working fine (I refactored the code to create a partitioner called p, but that does not affect the behavior):
open System.Threading.Tasks
open System.Collections.Concurrent
let PROCS = 10
let low, high = 0, 100
let p = Partitioner.Create(low, high+1, high+1-low/(PROCS*3))
Parallel.ForEach(p, (fun j ->
printfn "%A" j // Print the desired range (using %A as it is a tuple)
)) |> ignore
It is important that the value j is actually a pair of type int * int, so if the body uses it in a wrong way (e.g. as an int), you will get the error. In that case, you can add a type annotation to j and you would get a more useful error elsewhere:
Parallel.ForEach(p, (fun (j:int * int) ->
printfn "%d" j // Error here, because `j` is used as an int, but it is a pair!
)) |> ignore
This means that if you want to perform something for all j values in the original range, you need to write something like this:
Parallel.ForEach(p, (fun (loJ, hiJ) ->
for j in loJ .. hiJ - 1 do // Iterate over all js in this partition
printfn "%d" j // process the current j
)) |> ignore
Aside, I guess that the last argument to Partitioner.Create should actually be (high+1-low)/(PROCS*3) - you probably want to divide the total number of steps, not just the low value.
I have this code written for a Project Euler problem in c++:
int sum = 0;
for(int i =0; i < 1000; i++)
{
//Check if multiple of 3 but not multiple of 5 to prevent duplicate
sum += i % 3 == 0 && i % 5 != 0 ? i: 0;
//check for all multiple of 5, including those of 3
sum += i % 5 == 0 ? i: 0;
}
cout << sum;
I'm trying to learn f# and rewriting this in f#. This is what I have so far:
open System
//function to calculate the multiples
let multiple3v5 num =
num
//function to calculate sum of list items
let rec SumList xs =
match xs with
| [] -> 0
| y::ys -> y + SumList ys
let sum = Array.map multiple3v5 [|1 .. 1000|]
What I have may be complete nonsense...so help please?
Your sumList function is a good start. It already iterates (recursively) over the entire list, so you don't need to wrap it in an additional Array.map. You just need to extend your sumList so that it adds the number only when it matches the specified condition.
Here is a solution to a simplified problem - add all numbers that are divisible by 3:
open System
let rec sumList xs =
match xs with
| [] -> 0 // If the list is empty, the sum is zero
| y::ys when y % 3 = 0 ->
// If the list starts with y that is divisible by 3, then we add 'y' to the
// sum that we get by recursively processing the rest of the list
y + sumList ys
| y::ys ->
// This will only execute when y is not divisible by 3, so we just
// recursively process the rest of the list and return
/// that (without adding current value)
sumList ys
// For testing, let's sum all numbers divisble by 3 between 1 and 10.
let sum = sumList [ 1 .. 10 ]
This is the basic way of writing the function using explicit recursion. In practice, the solution by jpalmer is how I'd solve it too, but it is useful to write a few recursive functions yourself if you're learning F#.
The accumulator parameter mentioned by sashang is a more advanced way to write this. You'll need to do that if you want to run the function on large inputs (which is likely the case in Euler problem). When using accumulator parameter, the function can be written using tail recursion, so it avoids stack overflow even when processing long lists.
The idea of a accumulator-based version is that the function takes additional parameter, which represents the sum calculated so far.
let rec sumList xs sumSoFar = ...
When you call it initially, you write sumList [ ... ] 0. The recursive calls will not call y + sumList xs, but will instead add y to the accumulator and then make the recursive call sumList xs (y + sumSoFar). This way, the F# compiler can do tail-call optimization and it will translate code to a loop (similar to the C++ version).
I'm not sure if translating from an imperative language solution is a good approach to developing a functional mindset as instrument (C++ in your case) had already defined an (imperative) approach to solution, so it's better sticking to original problem outlay.
Overall tasks from Project Euler are excellent for mastering many F# facilities. For example, you may use list comprehensions like in the snippet below
// multipleOf3Or5 function definition is left for your exercise
let sumOfMultiples n =
[ for x in 1 .. n do if multipleOf3Or5 x then yield x] |> List.sum
sumOfMultiples 999
or you can a bit generalize the solution suggested by #jpalmer by exploiting laziness:
Seq.initInfinite id
|> Seq.filter multipleOf3Or5
|> Seq.takeWhile ((>) 1000)
|> Seq.sum
or you may even use this opportunity to master active patterns:
let (|DivisibleBy|_) divisior num = if num % divisor = 0 the Some(num) else None
{1..999}
|> Seq.map (fun i ->
match i with | DivisibleBy 3 i -> i | DivisibleBy 5 i -> i | _ -> 0)
|> Seq.sum
All three variations above implement a common pattern of making a sequence of members with sought property and then folding it by calculating sum.
F# has many more functions than just map - this problem suggests using filter and sum, my approach would be something like
let valid n = Left as an exercise
let r =
[1..1000]
|> List.filter valid
|> List.sum
printfn "%i" r
I didn't want to do the whole problem, but filling in the missing function shouldn't be too hard
This is how you turn a loop with a counter into a recursive function. You do this by passing an accumulator parameter to the loop function that holds the current loop count.
For example:
let rec loop acc =
if acc = 10 then
printfn "endloop"
else
printfn "%d" acc
loop (acc + 1)
loop 0
This will stop when acc is 10.