# Learning F# - Project Euler #1

I’ve recently decided to start learning F# and my initial thoughts are that to learn the syntax effectively I should stick with writing code (and tests) just for domain logic and not think about IO (connecting to APIs, DBs, etc.)

I decided that something like Project Euler would be appropriate for learning the basic F# syntax. I’ve done some of these ‘code katas’ before but it’s been a good few years.

The first Project Euler is fairly simple and doesn’t require an special mathmatical skills.

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.

My only goal is to write a working solution in order to start learning the F# syntax.

## First attempt

I started off with an empty F# project using the XUnit template. - `dotnet new xunit --language f#`

I them wrote my first function

``````let multiple5 x = false
``````

Followed by some tests, which will fail to start with, to assert the behaviour of this function.

``````    [<Fact>]
let ``Test that multiple of 5 returns true for 5`` () =
Assert.True(multiple5 5)

[<Fact>]
let ``Test that multiple of 5 returns false for 21`` () =
Assert.False(multiple5 21)
``````

And then updated the `multiple5` function to fix the tests:

``````let multiple5 x = x % 5 = 0
``````

My initial hurdle was understanding the compiliation order is defined with the `fsproj` file. This was fairly simple however I made it more difficult as I knew I wanted to be able to test this app on the console and therefore ended up with a problem that my test file has to be later in the compilation order, so that it can reference the actual code, however I ended up with the following error:

``````error FS0433: A function labeled with the 'EntryPointAttribute' attribute must be the last declaration in the last file in the compilation sequence.
``````

The solution to this is to extract the EntryPoint method out into a seperate file that references the `Euler1` module. I actually think this is great as it’s forcing the domain logic to be in a seperate library from the console app code.

I continued with creating the complimenting function, `multiple3`:

``````let multiple3 x = x % 3 = 0
``````

And then a function which checks whether the parameter is a multiple of either 3 or 5

``````  let multiple3or5 x =
multiple3 x || multiple5 x
``````

Then it’s onto iterating over a sequence of numbers and filtering out the numbers which aren’t multiples of 3 or 5.

``````    let naturalsWhichAreMultiples x =
[|1..x-1|]
|> Array.filter(multiple3or5)
``````

The final piece of the puzzle is the sum of the numbers returned from the above function.

``````    let sumOfNaturals max =
naturalsWhichAreMultiples max
|> Array.sum
``````

To tie everything together and to get the answer for the project euler problem I call this last function from the app Entry Point. Here is the final `Program.fs`

``````module Program
open Euler1
[<EntryPoint>]
let main args =
let max = args |> int
let sum = sumOfNaturals max
printf \$"Sum of natural numbers which are multiples of 3 or 5 to %i{max} is %i{sum}"
0
``````

And the `Euler1` module.

``````module Euler1
let multiple3 x = x % 3 = 0

let multiple5 x = x % 5 = 0

let multiple3or5 x =
multiple3 x || multiple5 x

let naturalsWhichAreMultiples x =
[|1..x-1|]
|> Array.filter(multiple3or5)

let sumOfNaturals max =
naturalsWhichAreMultiples max
|> Array.sum
``````

This is a quite length solution to what is a very simple problem, there’s certainly ways to make the code much smaller but this will come with subsequent iterations.

## Second attempt

This second attempt is more of a refactor of the first, I’ve basically merged the code from the 5 functions in the above attempt into a single function. It looks a little more cryptic but I think that’s because I’m not used to reading F# code.

``````module Euler1
let sumOfNaturals max =
[1..max-1]
|> Seq.filter (fun x -> (x % 3 = 0) || (x % 5 = 0) )
|> Seq.reduce (+)
``````

The final statement could also be replaced with `sum`

``````    let sumOfNaturals max =
[1..max-1]
|> Seq.filter (fun x -> (x % 3 = 0) || (x % 5 = 0) )
|> Seq.sum
``````