[Haskell-cafe] Type conversion problems

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>


More information about the Haskell-Cafe mailing list