2009-11-30 2 views
2

Travailler à partir de RWH, chapitre 3 question 5 demandes Je crée une fonction pour tester l'existence d'un paldindrome.Haskell question à propos de la fonction

j'ai écrit cela, mais il ne fonctionne pas

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

Je reçois cette erreur lorsque je tente de l'exécuter:

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) 

Je suis confus ce que je fais mal? Je sais qu'un paldindrome pourrait aussi bien être testé avec a == reverse a, mais maintenant je veux trouver l'erreur sur mon chemin.

MISE À JOUR: l'une des erreurs avec le code a été fixé par une suggestion par le juge, la question a été mis à jour pour refléter le problème restant

+0

Un test plus simple serait: 'isPalindrome x = (montrer x) == (inverse $ show x)' re –

+0

: jonno, je ne pense pas que le spectacle, ou parens sont nécessaires. 'isPalindrome = x == reverse x' –

Répondre

5

L'expression

take n a == take n $ reverse a 

obtient analyse syntaxique des

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

car l'opérateur $ a la priorité 0, plus bas que le == ou.

Vous devez l'expression:

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

En outre, s'il vous plaît respecter le Haskell et utiliser length a plutôt que length (a). Vous devez également utiliser length a `div` 2 plutôt que length a/2. La fonction div est une division entière, résultant en un nombre entier.

1

Deux problèmes.

En premier lieu, le problème de priorité indiqué par le juge: vous avez besoin (take n $ reverse a) ou take n (reverse a)

Deuxièmement, vous ne pouvez diviser rationals, pas des entiers, si vous voulez vraiment

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

Ou, comme indiqué par le juge - si l'upvote plutôt que moi pour cela - l'utilisation division entière div au lieu de (/) et vous n'avez pas besoin toRational

(Il pourrait être possib pour se débarrasser des parens ici, mais je ne sais pas si ça en vaut la peine ...)

0

Haskell ne fera aucune sorte de conversion automatique entre les nombres entiers et à virgule flottante quand il voit des expressions comme length a/2 . Si vous souhaitez diviser 2 numéros de type Int en ignorant les autres, utilisez div.

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