Difference between revisions of "Converting numbers"
m (added FAQ and Idioms categories) 
(realToFrac) 

Line 1:  Line 1:  
Converting between numerical types in Haskell must be done explicitly. This is unlike languages (such as C or Java) which automatically cast between numerical types in certain situations. 
Converting between numerical types in Haskell must be done explicitly. This is unlike languages (such as C or Java) which automatically cast between numerical types in certain situations. 

−  == Converting from 
+  == Converting from integers and between integer types == 
Integral types are ones which may only contain whole numbers and not fractions. <hask>Int</hask> (fixedsize machine integers) and <hask>Integer</hask> (arbitrary precision integers) are the two Integral types in the standard Haskell libraries. 
Integral types are ones which may only contain whole numbers and not fractions. <hask>Int</hask> (fixedsize machine integers) and <hask>Integer</hask> (arbitrary precision integers) are the two Integral types in the standard Haskell libraries. 

−  The workhorse for converting Integral types is <hask>fromIntegral</hask>, which will convert any integral type into any numeric type (e.g. <hask>Rational</hask>, <hask>Double</hask>...): 
+  The workhorse for converting Integral types is <hask>fromIntegral</hask>, which will convert any integral type into any numeric type (e.g. <hask>Rational</hask>, <hask>Double</hask>, <hask>Int16</hask> ...): 
<haskell> 
<haskell> 

fromIntegral :: (Num b, Integral a) => a > b 
fromIntegral :: (Num b, Integral a) => a > b 

Line 26:  Line 26:  
This is an inherently lossy transformation since integral types cannot express nonwhole numbers. Depending on how you wish to convert, you might choose one of several methods. 
This is an inherently lossy transformation since integral types cannot express nonwhole numbers. Depending on how you wish to convert, you might choose one of several methods. 

−  * <hask>ceiling</hask> 
+  * <hask>ceiling :: (RealFrac a, Integral b) => a > b</hask> 
−  * <hask>floor</hask> 
+  * <hask>floor :: (RealFrac a, Integral b) => a > b</hask> 
−  * <hask>truncate</hask> 
+  * <hask>truncate :: (RealFrac a, Integral b) => a > b</hask> 
−  * <hask>round</hask> 
+  * <hask>round :: (RealFrac a, Integral b) => a > b</hask> 
+  
+  == Converting between float types == 

+  
+  Say, conversion from Float to Double and back. 

+  
+  * <hask>realToFrac :: (Real a, Fractional b) => a > b</hask> 

+  * <hask>fromRational . toRational :: (Real a, Fractional b) => a > b</hask> 

== Automatic conversion == 
== Automatic conversion == 
Revision as of 21:22, 27 November 2007
Converting between numerical types in Haskell must be done explicitly. This is unlike languages (such as C or Java) which automatically cast between numerical types in certain situations.
Contents
Converting from integers and between integer types
Integral types are ones which may only contain whole numbers and not fractions. Int
(fixedsize machine integers) and Integer
(arbitrary precision integers) are the two Integral types in the standard Haskell libraries.
The workhorse for converting Integral types is fromIntegral
, which will convert any integral type into any numeric type (e.g. Rational
, Double
, Int16
...):
fromIntegral :: (Num b, Integral a) => a > b
For example, if you have an Int
value n
, you cannot take its square root by typing sqrt n
, since sqrt
may only be applied to Floating values. Instead, you must write sqrt (fromIntegral n)
to explicitly convert n
to a nonintegral type.
Converting to Rational
To convert something to a Rational
type, you can use the function toRational
:
toRational :: (Real a) => a > Rational
Values of type Rational
represent rational numbers exactly as the ratio of two Integer
s. Applying toRational
to an Integral
value n
will produce the rational number n % 1
; applying toRational
to a decimal (i.e. Fractional
or Floating
) value will produce a rational approximation.
You can also construct Rational
values explicitly using the %
operator.
Converting to Integral
This is an inherently lossy transformation since integral types cannot express nonwhole numbers. Depending on how you wish to convert, you might choose one of several methods.

ceiling :: (RealFrac a, Integral b) => a > b

floor :: (RealFrac a, Integral b) => a > b

truncate :: (RealFrac a, Integral b) => a > b

round :: (RealFrac a, Integral b) => a > b
Converting between float types
Say, conversion from Float to Double and back.

realToFrac :: (Real a, Fractional b) => a > b

fromRational . toRational :: (Real a, Fractional b) => a > b
Automatic conversion
Repeatedly people ask for automatic conversion between numbers. This is usually not a good idea; for more information, refer to the thoughts about a Generic number type.
original
Hi, I am trying to write some funs that convert between two coordinate systems. The first coordinate system, which ill call coord1, starts in the upper left at (0, 0) and ends in the lower right at (500, 500). Coordinates in coord1 have type (Int, Int). The second coord system, which ill call coord2, starts in the lower left at (0.0, 0.0) and ends in the upper right at (1.0, 1.0). Coords in coord2 have type (Float, Float). I was hoping someone could help me figure out how I can rewrite the two functions below so that the type checker will accept them.
coord1ToCoord2 :: (Int, Int) > (Float, Float)
coord1ToCoord2 (x, y) = (x/500, (500y)/500)
coord2ToCoord1 :: (Float, Float) > (Int, Int)
coord2ToCoord1 (x, y) = (500/(1/x), 500  500/(1/y))
examples of what i want. i think i have the logic right :)
coord1ToCoord2 (0, 0) > (0.0, 1.0)
coord1ToCoord2 (250, 250) > (0.5, 0.5)
coord1ToCoord2 (350, 350) > (0.7, 0.3)
coord1ToCoord2 (500, 500) > (1.0, 0.0)
coord2ToCoord1 (0.0, 0.0) > (0, 500)
coord2ToCoord1 (0.5, 0.5) > (250, 250)
coord2ToCoord1 (0.7, 0.7) > (350, 150)
coord2ToCoord1 (1.0, 1.0) > (500, 0)
Ah. I realize what is messing me up.
When i saw an expression like
500 * 0.2
i had assumed that 500 :: Integer because it didnt end in a .0. but it actually has type Double. so my problem was i would do something like this
(toInteger (500 :: Int)) * 0.2
which of course the typechecker wouldnt accept. now that i have rid myself of my incorrect assumptions i see that i should be writing
(fromRational (toRational (500 :: Int)) * 0.2) :: Float
now that i have a better understanding i am able to write my funs. thank you for your help :)