Question

J'apprends Haskell et coincé à essayer de comprendre le système de type.

Je suis en train d'écrire une fonction qui renvoie la longueur de la série demi-pension ou trois plus un »pour une entrée. Voici ma tentative de la fonction, en utilisant une approche récursive (la fonction est valable pour les entrées intégrales uniquement):

hotpo :: (Integral a) => a->a
hotpo n = hotpoHelper n 1

hotpoHelper:: (Integral a) => a->a->a
hotpoHelper 1 n = n
hotpoHelper num count
    | even num = hotpoHelper (truncate (num/2)) (count+1)
    | otherwise = hotpoHelper (3*num+1) (count+1)

Voici l'erreur que je reçois lorsque je tente de charger ce fichier dans GHC 6.12.3

test.hs:8:30:
    Could not deduce (RealFrac a) from the context (Integral a)
      arising from a use of `truncate' at test.hs:8:30-45
    Possible fix:
      add (RealFrac a) to the context of
        the type signature for `hotpoHelper'
    In the first argument of `hotpoHelper', namely
        `(truncate (num / 2))'
    In the expression: hotpoHelper (truncate (num / 2)) (count + 1)
    In the definition of `hotpoHelper':
        hotpoHelper num count
                      | even num = hotpoHelper (truncate (num / 2)) (count + 1)
                      | otherwise = hotpoHelper (3 * num + 1) (count + 1)

take (truncate (5/2)) [1,2,3] fonctionne, donc je suis incapable de comprendre ce message d'erreur. Où vais-je tort?

Était-ce utile?

La solution

L'opérateur / dans Haskell est utilisé pour la division à virgule flottante. Si vous ne voulais vraiment utiliser la division à virgule flottante et truncate, vous utiliseriez fromIntegral sur num premier à le convertir en un nombre à virgule flottante. L'erreur que vous obtenez dit que vous ne pouvez pas utiliser division fractionnaire sur un nombre entier (5/2 fonctionne parce que le compilateur infère un type à virgule flottante pour les deux numéros). Cependant, vous pouvez faire ce que vous voulez beaucoup plus facilement, en utilisant la fonction div. Ceci est généralement utilisé infix, en entourant le nom de la fonction avec backquotes (cela fonctionne pour toute fonction Haskell):

| even num = hotpoHelper (num `div` 2) (count+1)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top