views:

223

answers:

3

Working out of RWH, Chapter 3 question 5 requests I create a function to test for the existence of a paldindrome.

I wrote this, but it doesn't work

pCheck :: (Eq a) => [a] -> Bool;
pCheck a = take n a == ( take n $ reverse a )
  where n = floor ( length a / 2 )

I get this error when I try to run it:

No instance for (RealFrac Int)
  arising from a use of `floor' at len.hs:13:11-32
Possible fix: add an instance declaration for (RealFrac Int)
In the expression: floor (length a / 2)
In the definition of `n': n = floor (length a / 2)
In the definition of `pCheck':
    pCheck a = take n a == (take n $ reverse a)
             where
                 n = floor (length a / 2)

I'm confused what am I doing wrong? I know a paldindrome could just as well be tested with a == reverse a, but now I want to find the error in my way.

UPDATE: one of the errors with the code was fixed by a suggestion by Justice, the question has been updated to reflect the remaining problem

+3  A: 

The expression

take n a == take n $ reverse a

gets parsed as

(take n a == take n) $ (reverse a)

because the $ operator has precedence 0, lower even than the == operator.

You need the expression:

take n a == (take n $ reverse a)

Also, please respect the Haskell and use length a rather than length (a). You should also use length a `div` 2 rather than length a / 2. The function div is integer division, resulting in an integer.

Justice
+1  A: 

Two problems.

First, the precedence problem noted by Justice: you need (take n $ reverse a) or take n (reverse a)

Second, you can only divide rationals, not integers, so you really want

  where n = floor $ (toRational $ length $ reverse a) / 2

Or, as noted by Justice -- so upvote him rather than me for this -- use integer division div instead of (/) and then you don't need toRational

(It might be possible to get rid of the parens here, but I don't know if it's worth the effort...)

Andrew Jaffe
A: 

Haskell won't do any kind of automatic conversion between integral and floating point numbers when it sees expressions like length a / 2. If you want to divide 2 numbers of type Int ignoring any remainders, use div.

Prelude> 2 `div` 2
1
Prelude> 3 `div` 2
1
Prelude> 4 `div` 2
2
Prelude> 5 `div` 2
2
Prelude>
Michael Steele