Statically-typed read-only attributes

I have tried to create read-only attributes in htoolkit. It's easy, as any of you will already know: ------------------------------------------ class GetterAttr attr where getterAttr :: attr a b -> a -> IO b instance GetterAttr Attr where getterAttr (Attr getter setter) = getter data RAttr w a = RAttr (w -> IO a) instance GetterAttr RAttr where getterAttr (RAttr getter) = getter -- | Get an attribute get :: (GetterAttr attr) => w -> attr w a -> IO a get w a = getterAttr a w -- | Define a read-only attribute. Takes the name of the attribute as its first argument. readAttr :: (w -> IO a) -> RAttr w a readAttr getter = RAttr getter --- The rest is in Attr.hs------------------------------------- I have managed to compile htk with this modification, however it turns out that there are classes in htk like -- | Widgets that has specified integer position. class Positioned w where -- | The widget position pos :: Attr w Int Now, a programmer finding an instance of this class will think that he can move the object by setting the attribute. But menus are the only instance of this class, wich I changed to pos::Rattr w Int, because menus can't be moved. This raises the problem: what if I have also "instance Positioned Window"? Well, this problem has many solutions, the simplest of wich is *not* to have statically read-only attributes. I would rather try other solutions, however they might complicate the class and type hierarchy. What do you all think about this? Vincenzo

Nick Name wrote:
[...] This raises the problem: what if I have also "instance Positioned Window"? Well, this problem has many solutions, the simplest of wich is *not* to have statically read-only attributes. I would rather try other solutions, however they might complicate the class and type hierarchy.
What do you all think about this?
I think that the distinction (read-only, write-only, read-write) is very important for a good API design: Runtime tests are evil when errors could have been caught at compile time. The poor programmer would be forced to consult the documentation for every widget to see if getting and/or setting a particular attribute/property is allowed or not. :-P My OpenGL/GLUT binding relies very heavily on "state variables", which are very similar to the stuff in HToolkit and other proposals on this GUI list: http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/libraries/OpenGL/Graphics/Rendering/OpenGL/GL/StateVar.hs?rev=1.6&content-type=text/x-cvsweb-markup The main difference is that there is no `w' (widget) argument, because OpenGL/GLUT/OpenAL/... are based on an implicit context, which can be changed separately outside the core API. In the case of OpenGL, the context is the whole OpenGL state machine, which is typically a window-local entity managed by a toolkit. Because of this, my get/set API is a bit simpler, but I'm quite interested in a general (H98 conformant!) API for use in the GUI APIs and my stuff. Cheers, S.

Sven Panne wrote:
[...] This raises the problem: what if I have also "instance Positioned Window"? Well, this problem has many solutions, the simplest of wich is *not* to have statically read-only attributes. I would rather try other solutions, however they might complicate the class and type hierarchy.
What do you all think about this?
I think that the distinction (read-only, write-only, read-write) is very important for a good API design:
Reminder: under Xt, an attribute has three such "flags":
[C] Can be set when the widget is created (XtCreateWidget etc).
[S] Can be set after the widget is created (XtSetValues etc).
[G] Can be retrieved (XtGetValues etc).
These are all independent, although some combinations are more common
than others:
+ Attributes tend to be CSG unless there is a reason to the contrary.
+ Callback lists are invariably C; once the widget is created, you
have to use Xt{Add,Remove}Callback rather than replacing the entire
list.
+ C without S is quite common; attributes which dictate a specific
"role" for a widget (e.g. XmNrowColumnType) usually can't be changed.
+ S without C typically corresponds to attributes types for which a
value can't reasonably be constructed before the widget has been
created. E.g. for compound widgets (e.g. OK/Cancel dialogs), the
attributes which specify the child widgets (e.g. the OK/Cancel
buttons) are SG.
+ The absence of G is not uncommon; this typically means that the
resource value is converted to an internal form in a way that can't
readily be reversed.
+ Just G (i.e. read-only) is common for values which are computed
rather than stored (e.g. XmNancestorSensitive).
--
Glynn Clements
participants (3)
-
Glynn Clements
-
Nick Name
-
Sven Panne