casting numerical types

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

casting numerical types

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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: casting numerical types

Cale Gibbard
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 <[hidden email]> 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
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>
>
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: casting numerical types

Matthias Fischmann


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 <[hidden email]>
> Cc: [hidden email]
> From: Cale Gibbard <[hidden email]>
> 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 <[hidden email]> 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
> > [hidden email]
> > 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:   [hidden email]
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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: casting numerical types

Malcolm Wallace
Matthias Fischmann <[hidden email]> 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))

Regards,
    Malcolm
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: casting numerical types

Matthias Fischmann

On Sun, Apr 02, 2006 at 10:53:02AM +0100, Malcolm Wallace wrote:

> To: [hidden email]
> From: Malcolm Wallace <[hidden email]>
> Date: Sun, 2 Apr 2006 10:53:02 +0100
> Subject: Re: [Haskell-cafe] casting numerical types
>
> Matthias Fischmann <[hidden email]> 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.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

signature.asc (196 bytes) Download Attachment