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
source to share
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
source to share
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.
source to share