I'm trying to learn F# right now coming from C# and I'm finding it a great difficulty to "reconfigure" my mind to the functional programming mindset. So I'm going to attempt a few Project Euler problems to learn how to code functionally.
Here's my attempt at problem 1, now I'm wondering prorimarily, is this an idiomatic approach?
// Project Euler - Problem 1
// If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
// Find the sum of all the multiples of 3 or 5 below 1000.
#light
open System
let multiples = [for n in 1..1000 do if n % 3 = 0 || n % 5 = 0 then yield n]
let sum = List.sum multiples
printfn "The sum of all multiples are: %d" sum
ignore (Console.ReadKey ())
2 Answers 2
Some changes:
You don't need #light
any more. I would also use |>
more (this is more useful in more complex examples where it helps type inference.
open System
[for n in 1..1000 do if n % 3 = 0 || n % 5 = 0 then yield n]
|> List.sum
|> printfn "The sum of all multiples are: %d"
Console.ReadKey () |> ignore
-
1\$\begingroup\$ What exactly does
|>
do? :) \$\endgroup\$Overly Excessive– Overly Excessive2014年10月30日 11:58:31 +00:00Commented Oct 30, 2014 at 11:58 -
2\$\begingroup\$ @OverlyExcessive =
a |> b
is exactly the same asb(a)
\$\endgroup\$John Palmer– John Palmer2014年10月30日 12:03:21 +00:00Commented Oct 30, 2014 at 12:03 -
\$\begingroup\$ well no, given
b(a)
you can dob(a).foo
but nota |> b.foo
\$\endgroup\$Maslow– Maslow2014年10月30日 15:42:38 +00:00Commented Oct 30, 2014 at 15:42 -
\$\begingroup\$ @Maslow I don't know F#, but wouldn't it be possibly to do
(a |> b).foo
? \$\endgroup\$11684– 116842014年10月30日 19:21:06 +00:00Commented Oct 30, 2014 at 19:21 -
\$\begingroup\$ yes, but he said exactly the same which is mostly accurate, but not entirely \$\endgroup\$Maslow– Maslow2014年10月30日 23:35:09 +00:00Commented Oct 30, 2014 at 23:35
I think you should use sequence expressions only when you need them. In simple cases like yours, use existing functions, like List.filter
. When combined with the pipe operation, your code could look like this:
let sum =
[1..1000]
|> List.filter (fun n -> n % 3 = 0 || n % 5 = 0)
|> List.sum
-
\$\begingroup\$ What is the advantage of this over sequence expression? Is this more idiomatic :) ? \$\endgroup\$Overly Excessive– Overly Excessive2014年10月30日 17:06:29 +00:00Commented Oct 30, 2014 at 17:06
-
\$\begingroup\$ I think that it's simpler and that the structure of the computation (some initial collection, then filter, then sum) is immediately visible. \$\endgroup\$svick– svick2014年10月30日 17:10:49 +00:00Commented Oct 30, 2014 at 17:10