Glynn Clements glynn.clements at virgin.net
Sun Jun 13 06:44:38 EDT 2004

```Christian Hofer wrote:

> Here is the part of my code that is troubling me:
>
> fac :: Integer -> Integer
> fac n = product [1..n]
>
> term :: Double -> Integer -> Double
> term x n = (-1.0::Double)**(fromInteger n) * (x**(fromInteger (2*n +
> 1))) /
> 	   (fromInteger (fac (2*n + 1)))
>
> The term function is supposed to be the direct translation of the
> formula of a term within the sum. But it isn't: it is actually
> cluttered with lots of type conversions, and I had a hard time figuring
> out how to make it work at all. I hope that this is not the easiest way
> to do that and I would appreciate any help on how to handle those type
> conversion issues...

> term :: Double -> Integer -> Double
> term x n = (-1.0::Double)**(fromInteger n) * (x**(fromInteger (2*n +
> 1))) /
> 	   (fromInteger (fac (2*n + 1)))

In this specific instance, you probably want ^ (or possibly ^^)
instead of **; these have types:

(^)            :: (Num a, Integral b) => a -> b -> a
(^^)           :: (Fractional a, Integral b) => a -> b -> a

The difference is that ^^ supports negative exponents.

Using ^, term can be simplified to:

term :: Double -> Integer -> Double
term x n = (-1.0)^n * x^(2*n + 1) / fromInteger (fac (2*n + 1))

You can't get rid of the conversion in the denominator, because fac
returns an integer but / isn't defined on integers.

More generally, the core arithmetic operators (+,-,*,/) all require
that both arguments have the same type, and Haskell doesn't perform
implicit type conversions.

One option is to declare your own operators, e.g.:

(!+), (!-), (!*), (!/) :: (Real a, Real b, Fractional c) => a -> b -> c
a !+ b = realToFrac a + realToFrac b
a !- b = realToFrac a - realToFrac b
a !* b = realToFrac a * realToFrac b
a !/ b = realToFrac a / realToFrac b

Each arguments can be any instance of Real (i.e. any of the built-in
numeric types except for Complex), and the result will be
automatically cast to any instance of Fractional.

However, in practice you may end up getting a lot of errors due to
ambiguous types for intermediate results, so it might be better to
force the return type to e.g. Double.

--
Glynn Clements <glynn.clements at virgin.net>
```