casting numerical types

hi all, this should be a quick one (for now I would be happy with a "that's impossible", just want to make sure I don't miss anything). I want to compute the average from a list of arbitrary numerical element type. I wanted to do this: avg :: (Num a) => [a] -> a avg xs = sum (map fromNum xs) / (fromIntegral (length xs)) but it doesn't compile. All I could get to work is this: avg :: (Fractional a) => [a] -> a avg xs = sum xs / (fromIntegral (length xs)) avgI :: (Integral a) => [a] -> Float avgI = avg . map fromIntegral The two function names for the same thing are tolerable, but not very elegant. Is there another option? Thanks, Matthias

Arbitrary numerical types don't support division. (They're rings, not
fields.) The
(Fractional a) => [a] -> a
type is the best you can do.
- Cale
On 01/04/06, Matthias Fischmann
hi all,
this should be a quick one (for now I would be happy with a "that's impossible", just want to make sure I don't miss anything). I want to compute the average from a list of arbitrary numerical element type. I wanted to do this:
avg :: (Num a) => [a] -> a avg xs = sum (map fromNum xs) / (fromIntegral (length xs))
but it doesn't compile. All I could get to work is this:
avg :: (Fractional a) => [a] -> a avg xs = sum xs / (fromIntegral (length xs))
avgI :: (Integral a) => [a] -> Float avgI = avg . map fromIntegral
The two function names for the same thing are tolerable, but not very elegant. Is there another option?
Thanks, Matthias
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux)
iD8DBQFELsI5TXPx/Y0ym6oRAuQuAKDJzqus2beMm5WKfJBupPTesm6XcQCgjohh yKhGfl6Wv3t97ZGfBYTXKQM= =mmOH -----END PGP SIGNATURE-----
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Ok. I was hoping that there was a common ancestor of Integral and Fractional. Now I realize that I can be more precise about what I wanted: avg :: (FractionalOrIntegral a) => [a] -> a avg xs = sum (map fromFractionalOrIntegral xs) / (fromIntegral (length xs)) But although it there may be a sound type system supporting this it looks a little weird... thanks, matthias On Sat, Apr 01, 2006 at 06:10:48PM -0500, Cale Gibbard wrote:
To: Matthias Fischmann
Cc: haskell-cafe@haskell.org From: Cale Gibbard Date: Sat, 1 Apr 2006 18:10:48 -0500 Subject: Re: [Haskell-cafe] casting numerical types Arbitrary numerical types don't support division. (They're rings, not fields.) The (Fractional a) => [a] -> a type is the best you can do.
- Cale
On 01/04/06, Matthias Fischmann
wrote: hi all,
this should be a quick one (for now I would be happy with a "that's impossible", just want to make sure I don't miss anything). I want to compute the average from a list of arbitrary numerical element type. I wanted to do this:
avg :: (Num a) => [a] -> a avg xs = sum (map fromNum xs) / (fromIntegral (length xs))
but it doesn't compile. All I could get to work is this:
avg :: (Fractional a) => [a] -> a avg xs = sum xs / (fromIntegral (length xs))
avgI :: (Integral a) => [a] -> Float avgI = avg . map fromIntegral
The two function names for the same thing are tolerable, but not very elegant. Is there another option?
Thanks, Matthias
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux)
iD8DBQFELsI5TXPx/Y0ym6oRAuQuAKDJzqus2beMm5WKfJBupPTesm6XcQCgjohh yKhGfl6Wv3t97ZGfBYTXKQM= =mmOH -----END PGP SIGNATURE-----
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Institute of Information Systems, Humboldt-Universitaet zu Berlin web: http://www.wiwi.hu-berlin.de/~fis/ e-mail: fis@wiwi.hu-berlin.de tel: +49 30 2093-5742 fax: +49 30 2093-5741 office: Spandauer Strasse 1, R.324, 10178 Berlin, Germany pgp: AD67 CF64 7BB4 3B9A 6F25 0996 4D73 F1FD 8D32 9BAA

Matthias Fischmann
avg :: (FractionalOrIntegral a) => [a] -> a avg xs = sum (map fromFractionalOrIntegral xs) / (fromIntegral (length xs))
Your condition is probably too strong. For one thing, there is no need to convert every element of the list being summed, just its result. Also, does the final result need to be the same type as the elements? avg :: (Num a, Fractional b) => [a] -> b avg xs = fromRational (sum xs % toInteger (length xs)) Regards, Malcolm

On Sun, Apr 02, 2006 at 10:53:02AM +0100, Malcolm Wallace wrote:
To: haskell-cafe@haskell.org From: Malcolm Wallace
Date: Sun, 2 Apr 2006 10:53:02 +0100 Subject: Re: [Haskell-cafe] casting numerical types Matthias Fischmann
writes: avg :: (FractionalOrIntegral a) => [a] -> a avg xs = sum (map fromFractionalOrIntegral xs) / (fromIntegral (length xs))
Your condition is probably too strong. For one thing, there is no need to convert every element of the list being summed, just its result. Also, does the final result need to be the same type as the elements?
avg :: (Num a, Fractional b) => [a] -> b avg xs = fromRational (sum xs % toInteger (length xs))
you are right, your version looks better, and i managed to make ghc eat these variants: avg' :: (RealFrac a, Fractional b) => [a] -> b avg' xs = fromRational (round (sum xs) % toInteger (length xs)) avg'' :: (RealFrac a, Fractional b) => a -> [a] -> b avg'' epsilon xs = fromRational ((1 % toInteger (length xs)) * approxRational (sum xs) epsilon) But the problem is that (%) requests integral types, and I do not want to round my input. Also, I have the same problem as above that Integral types are not RealFrac, so these do not accept [Int] as input. When I try yours, however, I get: Couldn't match the rigid variable `a' against `Integer' `a' is bound by the type signature for `avg' Expected type: a Inferred type: Integer In the application `toInteger (length xs)' In the second argument of `(%)', namely `toInteger (length xs)' So do I need 'toNum' now? m.
participants (3)
-
Cale Gibbard
-
Malcolm Wallace
-
Matthias Fischmann