Haskell: Problem Ergebnis der Division zu integralem Typ Umwandeln
Frage
Ich lerne Haskell und steckte versuchen, das Typ-System zu verstehen.
Ich versuche, eine Funktion zu schreiben, die die Länge der Serie ‚Die Hälfte oder Drei-Plus-Eins‘ für eine Eingabe zurückgibt. Hier ist mein Versuch, die Funktion, einen rekursiven Ansatz (die Funktion ist gültig für Integral-Eingänge):
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)
Dies ist die Störung, die ich erhalte, wenn ich versuche in GHC 6.12.3 diese Datei zu laden
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]
funktioniert, so dass ich nicht in der Lage diese Fehlermeldung zu verstehen.
Wo bin ich falsch gehen?
Lösung
Der /
Operator in Haskell ist für Floating-Point-Division verwendet. Wenn Sie wirklich Punktteilung und truncate
wollten verwenden schwimmend, dann würden Sie fromIntegral
auf num
verwenden es zuerst zu einer Gleitkommazahl zu konvertieren. Der Fehler, den Sie erhalten, ist zu sagen, dass Sie nicht eine Bruchteilungs auf einer ganzen Zahl (5/2 funktioniert, weil der Compiler folgert eine Gleitkomma-Typ für beide Zahlen) verwenden können. Allerdings können Sie tun, was Sie viel mehr wollen einfach, die div
Funktion. Dies wird normalerweise verwendet, Infix, durch rund um die Funktionsnamen mit einfachen Anführungszeichen (dies funktioniert für jede Haskell-Funktion):
| even num = hotpoHelper (num `div` 2) (count+1)