
Hi (16 :: Float) is a perfectly legitimate statement although I'm surprised that it's allowed in a type strong language such as Haskell. It's a bit like casting in good old C. What's going on here? Paul

On 28 May 2008, at 09:34, PR Stanley wrote:
Hi (16 :: Float) is a perfectly legitimate statement although I'm surprised that it's allowed in a type strong language such as Haskell. It's a bit like casting in good old C. What's going on here?
It's not a coercion -- it happens at compile time. In a coercion, 16 starts off it's runtime life as an integer, gets a couple of things done to it, and then is coerced into a floating point number. What's happening here is you are telling the compiler "I would like the number 16, but a floating point version of it please". That instance of 16 always will have type Float. Slightly more detail: numeric literals like this normally have the type Int, but get pre-processed by the compiler. Whenever you write 16, the compiler writes (fromInteger 16). This has the effect that instead of having the type Int, your literal has the type Num a => a. You adding the type signature constrains it to being a Float again. Bob

PR Stanley
(16 :: Float) is a perfectly legitimate statement although I'm surprised that it's allowed in a type strong language such as Haskell. It's a bit like casting in good old C. What's going on here?
The literal 16 is really shorthand for "fromIntegral (16::Integer)"¹, which is a perfectly good expression for any member of the Num class -- including Float. -k ¹ Possibly it's ::Int? -- If I haven't seen further, it is by standing in the footprints of giants

2008/5/28 PR Stanley
Hi (16 :: Float) is a perfectly legitimate statement although I'm surprised that it's allowed in a type strong language such as Haskell. It's a bit like casting in good old C. What's going on here?
Don't worry: it's not a cast. Numeric constants like "16" in Haskell have polymorphic types: Prelude> :t 16 16 :: (Num t) => t Prelude> :t 16.6 16.6 :: (Fractional t) => t Writing "16 :: Float" you are simply making the type explicit, and you can do it only in the context of the typeclass. Prelude> :t (16 :: Integer) (16 :: Integer) :: Integer This works because Integer is a type of the typeclass Num, but: Prelude> :t (16.5 :: Integer) <interactive>:1:1: No instance for (Fractional Integer) arising from the literal `16.5' at <interactive>:1:1-4 Possible fix: add an instance declaration for (Fractional Integer) This doesn't work. So everything is done at compile time, no casting (i.e. "believe me compiler, this it a Float") involved. Notice that during binding the numeric constants' type is always made explicit (if you want to know more, look for section 4.3.4 in the Haskell Report): Prelude> let a = 3 Prelude> :t a a :: Integer Prelude> let b = 3.3 Prelude> :t b b :: Double Prelude> b :: Float <interactive>:1:0: Couldn't match expected type `Float' against inferred type `Double' In the expression: b :: Float In the definition of `it': it = b :: Float Salvatore

To add to this: There are other constants which are polymorphic, not only
numbers. Examples where you could add type signatures to make the type
explicit are the empty list '[]' and the 'Nothing' constructor of 'Maybe a'.
Adding type signatures to these will not be type casts, but telling the
compiler that you want to specialize the given polymorphic entity.
Abhay
On Wed, May 28, 2008 at 1:27 PM, Salvatore Insalaco
Hi (16 :: Float) is a perfectly legitimate statement although I'm surprised that it's allowed in a type strong language such as Haskell. It's a bit
2008/5/28 PR Stanley
: like casting in good old C. What's going on here?
Don't worry: it's not a cast. Numeric constants like "16" in Haskell have polymorphic types: Prelude> :t 16 16 :: (Num t) => t Prelude> :t 16.6 16.6 :: (Fractional t) => t
Writing "16 :: Float" you are simply making the type explicit, and you can do it only in the context of the typeclass.
Prelude> :t (16 :: Integer) (16 :: Integer) :: Integer
This works because Integer is a type of the typeclass Num, but: Prelude> :t (16.5 :: Integer) <interactive>:1:1: No instance for (Fractional Integer) arising from the literal `16.5' at <interactive>:1:1-4 Possible fix: add an instance declaration for (Fractional Integer)
This doesn't work. So everything is done at compile time, no casting (i.e. "believe me compiler, this it a Float") involved.
Notice that during binding the numeric constants' type is always made explicit (if you want to know more, look for section 4.3.4 in the Haskell Report): Prelude> let a = 3 Prelude> :t a a :: Integer
Prelude> let b = 3.3 Prelude> :t b b :: Double
Prelude> b :: Float <interactive>:1:0: Couldn't match expected type `Float' against inferred type `Double' In the expression: b :: Float In the definition of `it': it = b :: Float
Salvatore _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

PR Stanley wrote:
Hi (16 :: Float) is a perfectly legitimate statement although I'm surprised that it's allowed in a type strong language such as Haskell. It's a bit like casting in good old C. What's going on here?
It's not a type cast, it's a class method: class Num n where ... fromInteger :: Integer -> n ... The literal "16" is interpretted as the function call "fromInteger 16". If you write a literal, the compiler will usually optimise away the function call leaving only a literal Float/Double/Int/Word16/whatever. Notice, however, that you can explicitly call this function yourself at any time to change the type of something. Note that this is *not* a type cast. It doesn't just change what type the type checker thinks the data is; it really does change the actual bit pattern in memory. (E.g., turning an Integer into a Word8, possibly causing the value to overflow and wrap around in the process!) It's really no more mysterious than the way "show" can transform many kinds of data into a String, and "read" can transform them back again. It's not bypassing the type system, it's doing a real type conversion. I hope that made sense...
participants (6)
-
Abhay Parvate
-
Andrew Coppin
-
Ketil Malde
-
PR Stanley
-
Salvatore Insalaco
-
Thomas Davie