Haskell вопрос о функции - PullRequest
       21

Haskell вопрос о функции

2 голосов
/ 30 ноября 2009

Работа над RWH, глава 3, вопрос 5, я создаю функцию для проверки существования палдиндрома.

Я написал это, но это не работает

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

Я получаю эту ошибку при попытке запустить:

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)

Я запутался, что я делаю не так? Я знаю, что с помощью a == reverse a можно точно так же протестировать палдиндром, но теперь я хочу найти ошибку на моем пути.

ОБНОВЛЕНИЕ: одна из ошибок в коде была исправлена ​​по предложению юстиции, вопрос был обновлен, чтобы отразить оставшуюся проблему

Ответы [ 3 ]

5 голосов
/ 30 ноября 2009

Выражение

take n a == take n $ reverse a

анализируется как

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

потому что оператор $ имеет приоритет 0, даже ниже, чем оператор ==.

Вам нужно выражение:

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

Также, пожалуйста, уважайте Haskell и используйте length a вместо length (a). Вы также должны использовать length a `div` 2 вместо length a / 2. Функция div является целочисленным делением, в результате чего получается целое число.

1 голос
/ 30 ноября 2009

Две проблемы.

Во-первых, проблема приоритетности, отмеченная юстицией: вам нужно (take n $ reverse a) или take n (reverse a)

Во-вторых, вы можете делить только рациональные числа, а не целые числа, поэтому вы действительно хотите

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

Или, как заметил Судья - так что за него проголосуйте, а не я, - используйте целочисленное деление div вместо (/), и тогда вам не понадобится toRational

(Возможно, здесь можно избавиться от паренов, но я не знаю, стоит ли это усилий ...)

0 голосов
/ 30 ноября 2009

Haskell не выполняет никакого автоматического преобразования между целыми числами и числами с плавающей запятой, когда видит выражения типа length a / 2 Если вы хотите разделить 2 числа типа Int, игнорируя остатки, используйте div.

Prelude> 2 `div` 2
1
Prelude> 3 `div` 2
1
Prelude> 4 `div` 2
2
Prelude> 5 `div` 2
2
Prelude>
...