Type Coercion

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

Type Coercion

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?
Paul

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

Re: Type Coercion

Thomas Davie

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

Re: Type Coercion

Ketil Malde-5
In reply to this post by PR Stanley
PR Stanley <[hidden email]> writes:

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

Re: Type Coercion

Salvatore Insalaco
In reply to this post by PR Stanley
2008/5/28 PR Stanley <[hidden email]>:
> 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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Type Coercion

Abhay Parvate
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 <[hidden email]> wrote:
2008/5/28 PR Stanley <[hidden email]>:
> 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
_______________________________________________
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: Type Coercion

Andrew Coppin
In reply to this post by PR Stanley
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...

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