Нет экземпляра для (Floating Int)

Я изучаю Хаскель. Я создал функцию, которая возвращает таблицу умножения до «n» в базе «b». Числа дополняются до 'w' цифр. В качестве последнего шага я хочу автоматически вычислить «w». Почему это не компилируется?

-- Number of digits needed for the multiplication table n*n in base 'base'
nOfDg :: Int -> Int-> Int 
nOfDg n base = 1 + floor ( logBase base (n*n)) 

ошибка:

No instance for (Floating Int)
     arising from a use of `logBase' at C:\haskel\dgnum.hs:4:24-38
   Possible fix: add an instance declaration for (Floating Int)
   In the first argument of `floor', namely `(logBase b (n * n))'
   In the second argument of `(+)', namely `floor (logBase b (n * n))'
   In the expression: 1 + floor (logBase b (n * n))

person danatel    schedule 28.12.2009    source источник


Ответы (3)


logBase принимает два параметра, которые реализуют плавающий класс типов. Вам нужно будет вызвать fromIntegral для параметров, прежде чем передавать их в logBase. Это скомпилировано для меня с 6.10.3:

nOfDg :: Int -> Int-> Int
nOfDg n base = 1 + floor ( logBase (fromIntegral base) (fromIntegral (n*n)))

Вы должны помнить, что Haskell очень строго типизирован, поэтому вы не можете просто предположить, что параметры Int, переданные вашей функции, будут автоматически приведены к числам с плавающей запятой, которые обычно принимают функции журнала.

person maxaposteriori    schedule 28.12.2009

logBase объявлен для работы с типами с плавающей запятой. Int не является типом с плавающей запятой, и в Haskell нет автоматического преобразования. Попробуй это:

-- Number of digits needed for the multiplication table n*n in base 'base'
nOfDg :: Int -> Float -> Int
nOfDg n base = 1 + floor (logBase base (fromIntegral (n*n)))
person Dan Dyer    schedule 28.12.2009
comment
Я думаю, вам также понадобится (fromIntegral base). - person Jason Orendorff; 28.12.2009
comment
@Jason: Не с тем типом, который Дэн дал этой функции, ты не будешь. - person Chuck; 28.12.2009
comment
Да, зависит от того, как вы хотите его использовать. Либо сделайте так, как у меня, если можно изменить сигнатуру типа, либо используйте версию Энди, если нет. - person Dan Dyer; 28.12.2009

Из прелюдии:

logBase :: Floating a => a -> a -> a

Это означает, что при использовании logBase вы должны использовать плавающий тип. Но Int не является плавающим типом, и для числовых типов нет автоматического преобразования, поэтому вам нужно преобразовать его из Int в Floating тип:

nOfDg n base = 1 + floor ( logBase (toEnum base) (toEnum n))

функция toEnum принимает целое число в качестве параметра и возвращает тип "Enum". Хорошая часть заключается в том, что Float является экземпляром Enum, поэтому вы можете использовать его.

toEnum :: Enum a => Int -> a

Вам следует прочитать/задокументировать классы стандартных типов в haskell для числовых типов (Num, Fractional, Integral, Floating...), поскольку они часто всплывают в коде, изучение преобразований может быть полезным.

Изменить: эта Вики-книга Haskell содержит очень полезную графику отношений между классами типов стандартов, включая числовые типы.

person Raoul Supercopter    schedule 28.12.2009