0
votes

I've got an issue with Haskell where it appears to be disliking the fact that I'm returning a Boolean statement from a helper function. I'm checking if the distance between two numbers in a list is very small (less than 0.01); and in the case where it is true, I return this number. In the case where it is false, I check the next two numbers in the list.

Code:

positionChecker Pos ns = if compareDistance(ns !! Pos, ns !! (Pos+1))
                         then Pos
                         else positionChecker(Pos+1) ns

compareDistance n1 n2 = if abs(n1 - n2) < 0.01
                         then True
                         else False

(NB: I've removed the preceeding code that builds the list and calls positionChecker, initialising it with position 0, and a list of numbers)

The above is returning the following error;

pchk.hs:9:49:
Couldn't match expected type ‘Bool’ with actual type ‘(a, a)’

Relevant bindings include
  ns :: [a] (bound at pchk.hs:9:21)
  positionChecker' :: Int -> [a] -> a (bound at pchk.hs:9:1)
In the first argument of ‘compareDistance’, namely
  ‘(ns !! Pos, ns !! (Pos + 1))’
In the expression:
  compareDistance (ns !! Pos, ns !! (Pos + 1))
In the expression:
  if compareDistance (ns !! Pos, ns !! (Pos + 1)) then
      ns !! (Pos + 1)
  else
      positionChecker' (Pos + 1) ns

Again, from what I can make it, haskell seems to be confused by the fact that compareDistance is returning a Bool type.

I understand that there are far more sensible approaches to this solution (inclusive of simple, single-function or single-line solutions); but I'm just trying to make sense of the above error so that I can learn where I'm going wrong in this type of approach to a problem.

3
Rule #1: Always add the type of a function. Types are there to help you and document your code.Shoe
Why isn't compareDistance simply: compareDistance n1 n2 = abs(n1 - n2) < 0.01?Shoe

3 Answers

3
votes

Some comments on seeing your code:

  • Only type names in Haskell start with Capital letter. So you have to fix this:

positionChecker Pos ns = ...

  • Don't use !! function, it's unsafe:

λ> [0,1] !! 3 *** Exception: Prelude.(!!): index too large

  • Always write type signature for your functions. That will help you in debugging your problem more easily.

  • Haskell has the concept currying. So you don't pass parameters like this:

compareDistance(ns !! Pos, ns !! (Pos+1))

but like this:

compareDistance (ns !! Pos) (ns !! (Pos+1))
2
votes

You are calling "compareDistance" with a tuple as parameter instead of giving it two arguments. Remove the brackets and the coma. It's Haskell, not C.

1
votes

This isn't how you call functions in Haskell. You don't use parentheses to call functions. What these parentheses actually do is turn the two values into a tuple, and then that tuple is passed as a single argument to the function, resulting in total chaos for the type checker.