Michael HönnigMichael Hönnig

Recently I, mostly used to object oriented programming languages like C++ and Java) started learning Haskell to get some untainted impression of the functional programming style. Of course, I’ve used some functional programming in Java 8, JavaScript and Kotlin, but I wanted it pure to get new insights.

About Haskell

Haskell[1] is a purely functional, lazily evaluated, strongly typed programming language with high use of type inference. In Haskell there are no explicit loops, no "gotos" and no modifiable variables (strict immutability[2]). Sounds rigid? That’s the challenge!

About Project Euler

Then I’ve found Project Euler[3], a collection of programming problems ideal to learn new programming languages. So I started and implemented its first challenge using Haskell:

Problem 001: Sum of Multiples[4]

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!

{-# LANGUAGE ExtendedDefaultRules #-}
-- the pragma above is for some automatic type conversions

module Main where

import Data.List (nub)
  -- keeps only the first occurrence of each element

import Text.Printf
import System.IO

-- found this solution by accident while looking up a function for 'unique' in Haskell:
simple_euler_001 = (sum . nub) ([3,6..999] ++ [5,10..999])

-- ========================================================
-- and here my solution:
-- --------------------------------------------------------
javagil_euler_001 :: Int -> Int-> Int -> Int
javagil_euler_001 n m below = sum $ nub 
  $ (multiplesOfBelow n below) ++ (multiplesOfBelow m below)
  where multiplesOfBelow i below = [i,(2*i)..(below-1)]
-- ========================================================

main :: IO ()
main = do
  printf "javagil Euler 001: for 3, 5 below 10) = %d (expected: 23)\n"
    (javagil_euler_001 3 5 10)
  printf "javagil Euler 001: for 3, 5 below 1000) = %d\n"
    (javagil_euler_001 3 5 1000)
  printf " simple Euler 001: for 3, 5 below 1000) = %d\n"
    simple_euler_001

Isn’t the simple solution amazingly simple?

Speaking about my solution: Seems I over engineered by using a parameterized function instead of constants. Ok, for an excuse, I was not yet used to how Project Euler means it’s problem descriptions ;-=)

Let’s point it out: The core of the solution, not counting the frame of the program like import and the printf is just 1 line of optional[5] type declaration and 3 lines of code.


[1]: Haskell: https://www.haskell.org/

[2]: Application state can only be kept either on the stack or outside of the Haskell world which is accessible through IO functions.

[3]: Project Euler Problems: https://projecteuler.net/archives

[4]: Project Euler Problem 1: https://projecteuler.net/problem=1

[5]: Te type of javagil_euler_001 could be inferred automatically as done for simple_euuler_002.