[GUI] get and set
Sun, 16 Feb 2003 18:56:22 +0100
Daan Leijen wrote:
> [...] An attribute has both a type "a" and a thing that it belongs
> to "w". I wonder why the "thing it belongs to" is absent from your
> approach as it seems quite fundamental to me.
Of course there is a "thing it belongs to" for state variables in
OpenGL, too: It's the current rendering context (= the big, fat OpenGL
state machine), but it is implicit in all OpenGL calls. Handling the
context is beyond OpenGL's scope and normally handled by a GUI
toolkit, e.g. GLUT. You could do this e.g. under X11 with GLX calls
like glXMakeContextCurrent, which associates a context with the
current OS thread (Hello, FFI list! :-), but this is rather
unusual. You normally have a single context per window, and that's it.
Furthermore, switching an OpenGL context could be rather heavyweight,
as it potentially involves a lot of "real world" state changes on your
graphics card (reprogramming texture units, swapping of display lists,
flushing rendering pipelines, etc.). So this implicitness was a rather
intentional design choice when the OpenGL API was created and should
not be re-introduced artificially afterwards.
> It allows you for example to organise the attributes in type classes
> and re-use the same attribute name for different kind of things.
Hmmm, For the reason stated above, I don't think that there will be
type classes in HOpenGL similar to the usual "has a label" stuff in
> [ some Haskell code for Attr, get, Prop, (=:), and set omitted ... ]
That's basically what Graphics.UI.GIO.Attributes does, or did I miss
> Now, regarding openGL with state variables, you would make
> attributes that work on those, for example:
> value :: Attr (IORef a) a
> value = Attr (getIORef) (setIORef)
> So, even openGL will assign attributes to certain kind of things.
Nope, state variables in OpenGL have nothing to do with IORefs or
something similar, they are entities from the current context (= state
machine), and are not mirrored on the Haskell side. If they can be
set, there is an OpenGL call to do that, and if they can be read,
there is an OpenGL call retrieving that part of the state. If one or
both of the calls are missing from the API, there is a very good
reason for this.
The "w" in GIO's API would always be "()" in HOpenGL, and should
therefore be hidden from the latter API. Otherwise the types and calls
would look rather strange, and people would start asking what this
omnipresent "()" should mean. In types the "()" could be hidden by
appropriate "type" definitions, in function calls the extra argument
can be supplied by a wrapper function.
> Furthermore, you can still make a read/write distinction by putting
> "get" and ":=" in classes as you do:
> class Readable attr where
> get :: attr w a -> w -> IO a
> class Writable attr where
> (=:) :: attr w a -> a -> Prop w
> instance Readable Attr where ...
> instance Writable Attr where ...
You can't make a distinction with a single Attr type, you need
different ones for readable, writeable and r/w attributes. It's
crucial IMHO that you get a type error when you e.g. apply "get" to a
> But I am personally a bit hesitant to do this as it might give rise
> to rather complex error messages [...]
Better a complex error message at compile time than a simple one at
runtime. :-) Seriously, I don't expect real problems if we stay within
> [...] Therefore, i am quite curious if the approach that is focused
> on "Attributes" as sketched in this mail will also work for openGL.
Despite my comments above, I think there is common ground: Doing some
trivial impedance matching (nuking the "()") won't pose real problems
in HOpenGL's case, so the question is: Can you fit the read/write
distinction into GIO?
BTW, I had a closer look at GLUT and OpenAL (something I really like
to write a binding for, too) and found that the concepts in question
would be rather beneficial for a Haskell API. OTOH, this should have
been expected, because those APIs are closely modeled after OpenGL.