Problems writing the first Haskell function
I am new to Haskell and my code will not compile.
multipleSum :: Int -> Int
multipleSum x = let recSum 0 b = b
recSum a b | a mod 3 == 0 = recSum a-1 b+a
| a mod 5 == 0 = recSum a-1 b+a
| otherwise = recSum a-1 b
in recSum x 0
These are the two errors I am getting, the first one occurs on line 3 and the second one on line 6. What am I doing wrong? (The function must be the sum of all multiples of 3 and 5 below n)
1.
Occurs check: cannot construct the infinite type: a ~ a -> a -> a
Expected type: (a -> a -> a) -> a -> a
Actual type: ((a -> a -> a) -> a -> a) -> (a -> a -> a) -> a -> a
Relevant bindings include
b :: (a -> a -> a) -> a -> a
(bound at src\Main.hs:5:30)
a :: (a -> a -> a) -> a -> a
(bound at src\Main.hs:5:28)
recSum :: ((a -> a -> a) -> a -> a)
-> ((a -> a -> a) -> a -> a) -> (a -> a -> a) -> a -> a
(bound at src\Main.hs:4:21)
In the first argument of `(-)', namely `recSum a'
In the first argument of `(+)', namely `recSum a - 1 b'
2.Couldn't match expected type `(a0 -> a0 -> a0) -> a0 -> a0'
with actual type `Int'
In the first argument of `recSum', namely `x'
In the expression: recSum x 0
Couldn't match expected type `Int'
with actual type `(a0 -> a0 -> a0) -> a0 -> a0'
Probable cause: `recSum' is applied to too few arguments
In the expression: recSum x 0
In the expression:
let
recSum 0 b = b
recSum a b
| a mod 3 == 0 = recSum a - 1 b + a
| a mod 5 == 0 = recSum a - 1 b + a
| otherwise = recSum a - 1 b
in recSum x 0
You have two syntax problems. The first has to do with the priority of functions and operators. Application function has the highest priority in Haskell, so it is recSum a-1 b+a
treated as the same as (recSum a)-(1 b)+a
. Instead, you need to write recSum (a-1) (b+a)
.
The second problem is that a mod 3
is is a function a
called with arguments mod
and 3
. To use mod
as infix operator , write it as
a `mod` 3
By combining both of these changes together, we will have
multipleSum :: Int -> Int
multipleSum x = let recSum 0 b = b
recSum a b | a `mod` 3 == 0 = recSum (a-1) (b+a)
| a `mod` 5 == 0 = recSum (a-1) (b+a)
| otherwise = recSum (a-1) b
in recSum x 0
First of all, the more type signatures you can get, the easier it is to debug, so I rewrote it as
multipleSum :: Int -> Int
multipleSum x = recSum x 0
recSum :: Int -> Int -> Int
recSum 0 b = b
recSum a b | a mod 3 == 0 = recSum a-1 b+a
| a mod 5 == 0 = recSum a-1 b+a
| otherwise = recSum a-1 b
and run it in ghci or hug.
Thus, I am getting an error a mod 3
.
Ok I have to write infix functions with backticks so this should be
recSum :: Int -> Int -> Int
recSum 0 b = b
recSum a b | a `mod` 3 == 0 = recSum a-1 b+a
| a `mod` 5 == 0 = recSum a-1 b+a
| otherwise = recSum a-1 b
Now I am getting errors about the number of arguments in recSum a-1 b+a
. This is because there should only be two, so I need parentheses if I'm going to pass something more complex than one variable, so I have to write
recSum :: Int -> Int -> Int
recSum 0 b = b
recSum a b | a `mod` 3 == 0 = recSum (a-1) (b+a)
| a `mod` 5 == 0 = recSum (a-1) (b+a)
| otherwise = recSum (a-1) b -- don't need brackets for b on its own
Now it's compiled, it's time to test it with various inputs to see if it does what it should.