[Haskell-cafe] Type conversion problems

2004-06-13 Thread Christian Hofer
Hi,
after some playing around with monad transformers and starting to like 
those specialities of Haskell, I am currently really feeling thrown 
back by a simple problem: trying to write a sine-function...

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

Thanks,
Chris
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Type conversion problems

2004-06-13 Thread Lauri Alanko
On Sun, Jun 13, 2004 at 11:15:28AM +0200, Christian Hofer wrote:
 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)))

Why do you have all those type annotations? Simply writing directly:

fac n = product [1..n]
term x n = -1 ** n * (x ** (2 * n + 1)) / fac (2 * n + 1)

gives you functions for which are inferred the types (which you can of
course also give explicitly if you want):

fac :: (Enum a, Num a) = a - a
term :: (Floating a, Enum a) = a - a - a

And the type variable a can then be instantiated for Double. If you
really need to take an Integer parameter, you only need a single
conversion:

term' x n = term x (fromIntegral n)

with the type:

term' :: (Floating a, Enum a, Integral b) = a - b - a

If all this looks confusing, then forget about polymorphism and just
give exact types in the type annotations:

fac :: Double - Double
fac n = product [1..n]

term :: Double - Double - Double
term x n = -1 ** n * (x ** (2 * n + 1)) / fac (2 * n + 1)

term' :: Double - Integer - Double
term' x n = term x (fromIntegral n)

Hope this helps.


Lauri Alanko
[EMAIL PROTECTED]
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Type conversion problems

2004-06-13 Thread Glynn Clements

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 [EMAIL PROTECTED]
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Type conversion problems

2004-06-13 Thread Christian Hofer
Am 13.06.2004 um 12:44 schrieb Glynn Clements:
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))
(Further interesting information snipped...)
Ok, I just didn't know this operator. This is actually exactly what I 
was hoping to be able to write.

Thanks,
Chris
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Type conversion problems

2004-06-13 Thread Glynn Clements

Lauri Alanko wrote:

  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)))
 
 Why do you have all those type annotations? Simply writing directly:
 
 fac n = product [1..n]
 term x n = -1 ** n * (x ** (2 * n + 1)) / fac (2 * n + 1)
 
 gives you functions for which are inferred the types (which you can of
 course also give explicitly if you want):
 
 fac :: (Enum a, Num a) = a - a
 term :: (Floating a, Enum a) = a - a - a
 
 And the type variable a can then be instantiated for Double.

Except that it's arguable that Double shouldn't be an instance of
Enum.

Really, this solution is relying upon a misfeature of the language;
one which won't work in the general case. Suppose that fac was a
different function, one which couldn't be defined as returning a
non-integral result without using an explicit (and conceptually
incorrect) type conversion.

-- 
Glynn Clements [EMAIL PROTECTED]
___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe