3

I'm currently working through the book Programming in Haskell (which is absolutely amazing so far), but ran into a problem in exercise 4.8.8.

The task is to implement the Luhn algorithm in Haskell, using a help function luhnDouble :: Int -> Int (which doubles a digit and subtracts 9 if the result is greater than 9) and the mod funcion.

Implementing the luhnDouble function was no problem, but I'm struggling to bring both of them into a function of type Int -> Int -> Int -> Int -> Bool.

I have tried doing it two ways:

luhn :: Int -> Int -> Int -> Int -> Bool
luhn w x y z = if (((luhnDouble w) + x + (luhnDouble y) + z) mod 10) == 0 then True
               else False

I receive a type error.

* Couldn't match expected type `(Integer -> Integer -> Integer)
                                -> Integer -> Integer'
              with actual type `Int'
* The function `(luhnDouble w) + x + (luhnDouble y) + z'
  is applied to two arguments,
  but its type `Int' has none
  In the first argument of `(==)', namely
    `(((luhnDouble w) + x + (luhnDouble y) + z) mod 10)'
  In the expression:
    (((luhnDouble w) + x + (luhnDouble y) + z) mod 10) == 0

But am I not giving the functions 4 Ints as arguments and getting a Bool as a result?

I then tried currying the function and using lambda expressions:

luhn :: Int -> (Int -> (Int -> Bool))
luhn = \w ->(\x ->(\y -> (\z -> ((luhnDouble w) + x + (luhnDouble y) + z mod 10))))

But I'm not sure how to bring in the if expression in here to get a Bool value as a result.

Could anyone help me out, and give me a tip how I could solve this?

Lubomír Sedlář
  • 1,580
  • 2
  • 17
  • 26
TheCoolFrood
  • 367
  • 2
  • 15

2 Answers2

3
luhn :: Int -> Int -> Int -> Int -> Bool
luhn w x y z = if (((luhnDouble w) + x + (luhnDouble y) + z) mod 10) == 0 then True
  1. You didn't give it an else after if.
  2. You are calling prefix mod, not infix `mod`.

Fix:

luhn :: Int -> Int -> Int -> Int -> Bool
luhn w x y z = if (((luhnDouble w) + x + (luhnDouble y) + z) `mod` 10) == 0
                  then True
                  else False

or

luhn :: Int -> Int -> Int -> Int -> Bool
luhn w x y z = if (mod ((luhnDouble w) + x + (luhnDouble y) + z) 10) == 0
                  then True
                  else False

or, a less redundant version:

luhn :: Int -> Int -> Int -> Int -> Bool
luhn w x y z = (mod ((luhnDouble w) + x + (luhnDouble y) + z) 10) == 0
chi
  • 111,837
  • 3
  • 133
  • 218
Rahn
  • 4,787
  • 4
  • 31
  • 57
1
luhn :: Int -> Int -> Int -> Int -> Bool
luhn w x y z = (luhnDouble w + x + luhnDouble y + z) `mod` 10 == 0

This will work

Brian McKenna
  • 45,528
  • 6
  • 61
  • 60