Gentle Introduction to Haskell 98, Online Supplement Part 20 Covers Section 10.4 > module Part20() where > import Complex Section: 10.4 Default Numeric Types Ambiguous contexts arise frequently in numeric expressions. When an expression which produces a value with a general type, such as `1' (same as `fromInteger 1'; the type is (Num a) => a), with another expression which `consumes' the type, such as `show' or `toInteger', ambiguity arises. This ambiguity can be resolved using expression type signatures, but this gets tedious fast! Assigning a type to the top level of an ambiguous expression does not help: the ambiguity does not propagate to the top level. > e1 :: String -- This type does not influence the type of the argument to show > e1 = show 1 -- Does this mean to show an Int or a Float or ... > e2 :: String > e2 = show (1 :: Float) > e3 :: String > e3 = show (1 :: Complex Float) The reason the first example works is that ambiguous numeric types are resolved using defaults. The defaults in effect here are Int and Double. Since Int `fits' in the expression for e1, Int is used. When Int is not valid (due to other context constraints), Double will be tried. This function defaults the type of the 2's to be Int > rms :: (Floating a) => a -> a -> a > rms x y = sqrt ((x^2 + y^2) * 0.5) One of the reasons for adding type signatures throughout these examples is to avoid unexpected defaulting. Many of the top level signatures are required to avoid ambiguity. Notice that defaulting applies only to numeric classes. The > -- show (read "xyz") -- Try this if you want! example uses only class Show so no defaulting occurs. Ambiguity also arises with polymorphic types. As discussed previously, expressions like [] have a similar problem. > e4 = [] -- Won't print since [] has type [a] and `a' is not known. Note the difference: even though the lists have no components, the type of component makes a difference in printing. > e5 = ([] :: [Int]) > e6 = ([] :: [Char]) Continued in part21.lhs