No instance for (Floating Int)

2019-01-19 14:56发布

I am learning Haskell. I have created function which returns multiplication table up to 'n' in base 'b'. Numbers are padded to 'w' digits. As the last step, I want to compute 'w' automatically. Why does this not compile?

-- 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)) 

error:

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))

3条回答
别忘想泡老子
2楼-- · 2019-01-19 15:07

From the Prelude :

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

It means that using logBase you must be using a floating type. But Int is not a floating Type, and there is no automatic conversion for numeric types, so you have to convert it from Int to a Floating type :

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

the toEnum function take an int as parameter and return an "Enum" type. The good part is that Float is an instance of Enum, so you could use it

toEnum :: Enum a => Int -> a

You should read/document you about standard type classes in haskell for numeric types (Num,Fractional,Integral, Floating...) as they often pop-up in code, learning conversions could be useful.

Edit : this Haskell Wiki Book provide a very useful graphic of relationship between standards type class, including numeric types.

查看更多
唯我独甜
3楼-- · 2019-01-19 15:13

logBase takes two parameters which implement the floating typeclass. You'll need to call fromIntegral on the parameters before passing them to logBase. This compiled for me with 6.10.3:

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

You have to remember that Haskell is very strongly typed, so you can't just assume that the Int parameters supplied to your function will automatically be coerced to the floating numbers that log functions generally take.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-01-19 15:33

logBase is declared to work on floating point types. Int is not a floating point type and there is no automatic conversion in Haskell. Try this:

-- 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)))
查看更多
登录 后发表回答