Haskell:将除法结果转换为整数类型的问题

vic*_*dev 1 haskell division typeclass collatz

我正在学习Haskell,并试图理解类型系统.

我正在尝试编写一个函数,它返回系列'Half或Three Plus One'的长度作为输入.这是我对函数的尝试,使用递归方法(该函数仅对整数输入有效):

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)
Run Code Online (Sandbox Code Playgroud)

这是我尝试在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)
Run Code Online (Sandbox Code Playgroud)

take (truncate (5/2)) [1,2,3]有效,所以我无法理解这个错误信息.我哪里错了?

Nei*_*own 10

/Haskell中的运算符用于浮点除法.如果你真的想用浮点除法和truncate,你会使用fromIntegralnum第一个将其转换为一个浮点数.你得到的错误是你不能在整数上使用小数除法(5/2可以工作,因为编译器会为两个数字推断浮点类型).但是,您可以使用该div功能更轻松地执行您想要的操作.这通常使用中缀,通过使用反引号包围函数名称(这适用于任何Haskell函数):

| even num = hotpoHelper (num `div` 2) (count+1)
Run Code Online (Sandbox Code Playgroud)