Haskell Type Coercion

haskell

Solution

If you just want the solution, look at the end.

You nearly answered your own question already. Literals in Haskell are overloaded:

Prelude> :t 3
3 :: Num a => a

Since `(*)` also has a `Num` constraint

Prelude> :t (*)
(*) :: Num a => a -> a -> a

this extends to the product:

Prelude> :t 3 * 20
3 * 20 :: Num a => a

So, depending on context, this can be specialized to be of type `Int`, `Integer`, `Float`, `Double`, `Rational` and more, as needed. In particular, as `Fractional` is a subclass of `Num`, it can be used without problems in a division, but then the constraint will become stronger and be for class `Fractional`:

Prelude> :t 3 * 20 / 4
3 * 20 / 4 :: Fractional a => a

The big difference is the identifier `c` is an `Integer`. The reason why a simple let-binding in GHCi prompt isn't assigned an overloaded type is the dreaded monomorphism restriction. In short: if you define a value that doesn't have any explicit arguments, then it cannot have overloaded type unless you provide an explicit type signature. Numeric types are then defaulted to `Integer`.

Once `c` is an `Integer`, the result of the multiplication is `Integer`, too:

Prelude> :t 3 * c
3 * c :: Integer

And `Integer` is not in the `Fractional` class.

There are two solutions to this problem.

Make sure your identifiers have overloaded type, too. In this case, it would be as simple as saying

  Prelude> let c :: Num a => a; c = 20
  Prelude> :t c
  c :: Num a => a

Use `fromIntegral` to cast an integral value to an arbitrary numeric value:

  Prelude> :t fromIntegral
  fromIntegral :: (Integral a, Num b) => a -> b
  Prelude> let c = 20
  Prelude> :t c
  c :: Integer
  Prelude> :t fromIntegral c
  fromIntegral c :: Num b => b
  Prelude> 3 * fromIntegral c / 4
  15.0

Problem

I trying to wrap my head around Haskell type coercion. Meaning, when does can one pass a value into a function without casting and how that works. Here is a specific example, but I am looking for a more general explanation I can use going forward to try and understand what is going on: ``` Prelude> 3 * 20 / 4 15.0 Prelude> let c = 20 Prelude> :t c c :: Integer Prelude> 3 * c / 4 <interactive>:94:7: No instance for (Fractional Integer) arising from a use of `/' Possible fix: add an instance declaration for (Fractional Integer) In the expression: 3 * c / 4 In an equation for `it': it = 3 * c / 4 ``` The type of (/) is Fractional a => a -> a -> a. So, I'm guessing that when I do "3 * 20" using literals, Haskell somehow assumes that the result of that expression is a Fractional. However, when a variable is used, it's type is predefined to be Integer based on the assignment. My first question is how to fix this. Do I need to cast the expression or convert it somehow? My second question is that this seems really weird to me that you can't do basic math without having to worry so much about int/float types. I mean there's an obvious way to convert automatically between these, why am I forced to think about this and deal with it? Am I doing something wrong to begin with? I am basically looking for a way to easily write simple arithmetic expressions without having to worry about the neaty greaty details and keeping the code nice and clean. In most top-level languages the compiler works for me -- not the other way around.

Original source