[Haskell-beginners] GLfloat cast... have I got it right?
Daniel Fischer
daniel.is.fischer at googlemail.com
Fri Jul 8 01:47:25 CEST 2011
On Friday 08 July 2011, 00:37:56, Arlen Cuss wrote:
> > The !a is, IIUIC, a strictness instruction that ensures that whatever
> > expression I put here is evaluated immediately i.e. no thunk is
> > generated and presumably no space leaks either: something rendering at
> > 60 fps with 'interesting' calculations for RGB values for example
> > could cripple the application!
>
> Correct. (I believe it forces the expression to WHNF, which basically
> means 'forces the value' in the case of things like numbers and floats,
> AFAIK, but I've only just learned about that syntax myself)
Right. Precisely, it forces the fields to WHNF *when the entire value is
forced to WHNF*.
With
data Foo a = F a a
(x :: Foo Int) `seq` ()
forces the constructor F but leaves the fields alone, so
(F undefined undefined) `seq` ()
evaluates to ().
With
data Bar a = B !a !a
(y :: Bar Int) `seq` ()
forces the constructor B and also the fields [to WHNF] (since the fields
have type Int, that means full evaluation), so
(B 3 undefined) `seq` ()
yields _|_. But
(B (3:undefined) (4:undefined)) `seq` ()
evaluates to ().
So putting a `!' on a component of, say, type String only forces it enough
to see whether it's empty or not. `!' is most useful for types where WHNF
implies sufficient evaluation, which means the constructors of that type
need to have strict fields too (if any). Types like Integer, Int, Word,
Double, Float have (in GHC) strict fields in the form of "raw bytes",
Data.Map has `!'-ed fields (but the values are lazy), so with
data Quux a b = Q ... !(Map a b) ...
forcing a value of such a type to WHNF also forces the entire spine of the
Map, which often is sufficient, but not always. If you also need the values
in the Map to be evaluated, you have to use other methods (normally it's
best to make sure the values are evaluated when they are inserted into the
Map, doing that later tends to be expensive).
>
> > But back to the syntax: I am guessing (and hoping I've got it right
> > for the *right* reasons) that it works because the definition says
> > "a" for all three and that explicitly typing the first one
> > automatically tells (infers!) the type inference system that the
> > other two are to be treated as GLfloat types too.
>
> Exactly. As you've specified one of them to be a given type (note that I
> think it would be slightly off the mark to call it a "cast" here [as per
> the subject], unless that terminology is the norm for numbers in Haskell
It's not. The term "cast" is rarely used in Haskell. For (0 :: Float) one
would rather say that one specifies the type.
But calling it a cast isn't wrong, since it means "apply this conversion
function to that value", what a cast in other languages means too.
However, there's a difference.
In C (Java, C#, ...), if I have
int x, y;
// stuff setting the values
I can do
double d = (double)x / y;
so I can tell the compiler explicitly to convert the one monomorphic value
to another type and the compiler automatically converts the other to the
same type to perform the calculation.
In Haskell, a) I cannot invoke a conversion function on a monomorphic value
by just giving a type signature, b) I have to explicitly convert all
involved values.
Re a): Number literals come with an implicit conversion function,
1234 and 5.678 stand for "fromInteger 1234" resp. "fromRational 5.678"
and a type signature tells the compiler which fromInteger/fromRational to
invoke. Number literals are polymorphic expressions and polymorphic
expressions can be "cast" to a specific type by a type signature [which
tells the compiler which fromInteger, return, ... to use]. To convert a
monomorphic expression, however, the conversion function has to be
explicitly invoked.
> -- it reads more [to me] like you're actually informing the typing
> engine that it *is* a GLfloat, not to make it into one!), the rest must
> follow by virtue of them sharing that type.
Yup. Per the data definition, they all have the same type, so when you know
one, you know them all.
More information about the Beginners
mailing list