Haskell: проблема преобразования результата деления в целочисленный тип - PullRequest
1 голос
/ 17 ноября 2010

Я изучаю Хаскель и застрял, пытаясь понять систему типов.

Я пытаюсь написать функцию, которая возвращает длину серии 'Half or 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)

Вот ошибка, которая появляется при попытке загрузить этот файл в 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] работает, поэтому я не могу понять это сообщение об ошибке. Куда я иду не так?

1 Ответ

10 голосов
/ 17 ноября 2010

Оператор / в Haskell используется для деления с плавающей запятой.Если вы действительно хотите использовать деление с плавающей запятой и truncate, вы сначала использовали бы fromIntegral на num, чтобы преобразовать его в число с плавающей запятой.Вы получаете сообщение о том, что вы не можете использовать дробное деление на целое число (5/2 работает, потому что компилятор выводит тип с плавающей запятой для обоих чисел).Однако вы можете делать то, что хотите, гораздо проще, используя функцию div.Обычно это инфикс, заключающий имя функции в кавычки (это работает для любой функции Haskell):

| even num = hotpoHelper (num `div` 2) (count+1)
...