Rivalez
Rivalez

Reputation: 83

mod, div in Haskell

Can someone explain why this doesn't work?

main = do
    let a = 50
    let y = 7
    let area = (a ** y) 
    print (area)   
    print (a `mod` y)

I expected it to print:

781250000000   -- 50 to the 7th power
1              -- remainder of 50/7

But instead I get a series of ambiguous type errors like this:

test.hs:2:13:
    No instance for (Num a0) arising from the literal `50'
    The type variable `a0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'

Upvotes: 5

Views: 6592

Answers (1)

Daniel Wagner
Daniel Wagner

Reputation: 152682

Simple; take a look at the types of (**) and mod:

Prelude> :t (**)
(**) :: Floating a => a -> a -> a
Prelude> :t mod
mod :: Integral a => a -> a -> a

It is a rare numeric type that has both the characteristics of an integer and the characteristics of a floating-point number. You have a couple of choices for dealing with this:

  1. Use an exponentiation operation that handles integer-like numbers well. For example, (^) :: (Integral b, Num a) => a -> b -> a.
  2. Use a modulus operation that handles floating-point numbers well. For example, mod' :: Real a => a -> a -> a.
  3. Explicitly convert to a floating-point type with realToFrac :: (Real a, Fractional b) => a -> b before calling (**).
  4. Explicitly convert to an integer-like type with floor :: (RealFrac a, Integral b) => a -> b (or another rounding function) before calling mod.

Upvotes: 9

Related Questions