[GUI] Type safe readonly and writeonly attributes with phantom types
Nick Name
nick.name at inwind.it
Tue Sep 16 01:56:29 EDT 2003
Yes, I ask dumb questions on haskell-cafe for a reason ;)
As the subject already states, I think that it's worth to be considered
to use phantom types and type classes to encode the access mode of an
attribute.
A first approach is the following:
---- Begin 1 ----
class ReadMode mode
class WriteMode mode
class Mode a
data Readable = Readable
data Writeable = Writeable
data ReadWrite = ReadWrite
instance ReadMode Readable
instance WriteMode Writeable
instance ReadMode ReadWrite
instance WriteMode ReadWrite
instance ReadMode a => ReadMode (a,b)
instance WriteMode b => WriteMode (a,b)
data Attr m w a = Attr (w -> IO a) (w -> a -> IO ())
newAttr :: (w -> IO a) -> (w -> a -> IO ()) -> Attr ReadWrite w a
readAttr :: (w -> IO a) -> Attr Readable w a
writeAttr :: (w -> a -> IO ()) -> Attr Writeable w a
get :: ReadMode m => w -> Attr m w a -> IO a
---- End 1 ----
However this has a problem: the combinatorial explosion of data
declarations to represent modes, if one has more than two
"switches" (as I will have in the next days ;-)
The second one, wich I particularly like, is:
---- Begin 2 ----
class ReadMode mode
class WriteMode mode
class Mode a
data Readable = Readable
data Writeable = Writeable
instance Mode Readable
instance Mode Writeable
instance ReadMode Readable
instance WriteMode Writeable
instance (Mode a,Mode b,ReadMode a) => ReadMode (a,b)
instance (Mode a,Mode b,WriteMode b) => WriteMode (a,b)
data Attr m w a = Attr (w -> IO a) (w -> a -> IO ())
newAttr :: (w -> IO a) -> (w -> a -> IO ()) ->
Attr (Readable,Writeable) w a
readAttr :: (w -> IO a) -> Attr Readable w a
writeAttr :: (w -> a -> IO ()) -> Attr Writeable w a
data Prop ...
(=:) :: WriteMode m => Attr m w a -> a -> Prop w
get :: ReadMode m => w -> Attr m w a -> IO a
set :: w -> [Prop w] -> IO ()
---- End 2 ----
Note that this is everything haskell98, and can be used (yes, I still
haven't tried to recompile htoolkit, but going to try now) like Attr.hs
is used right now.
This also can solve the already mentioned problem wich is:
"I want to breakdown my types in a class hierarchy, so I want to define
thing that, say, have a position. So I want to put the type "Menu" in
that class, and also the type "Window". But a window can be
repositioned, while a menu can't. So I have to make two classes, if I
have separated "ReadOnlyAttr" and "ReadWriteAttr" at the type level."
To solve this problem, unfortunately, I need multi-parameter type
classes, wich could be considered almost legal, but also functional
dependencies if I want to avoid type declarations everywhere (and even
in places where they aren't haskell98 anyway):
---- Begin 3 ----
class HasMyAttr w m | w -> m where
myAttr :: Attr m w ()
data TestRW = TestRW
data TestR = TestR
instance HasMyAttr TestRW (Readable,Writeable) where
myAttr = newAttr undefined undefined
instance HasMyAttr TestR Readable where
myAttr = readAttr undefined
t1 = set1 TestRW (myAttr =: ())
t2 = get TestRW myAttr
t3 = set1 TestR (myAttr =: ()) -- this row can't be compiled
t4 = get TestR myAttr
---- End 3 ----
But note how self documenting this code is: the two instance
declarations say exactly that "myAttr" is readable and writeable in
type TestRW, and read-only in testR. Besides, note that the mode system
is extensible: no one constrains an attribute to have a mode wich is
one of the types here mentioned, an user has just to conscientiously
put its own modes into the right typeclasses. However, if we wish not
to allow extention, we still can in some way.
Besides, I think that this mode system could be used even if one does
not want h98 extentions: it does not limit in any way (AFAIK) the
standard (type-correct) usage wrt the present implementation and adds
stronger type-checking.
I attach the complete modified Attr.hs for reference and wait hopefully
for some comment.
Vincenzo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Attr.hs
Type: text/x-c++src
Size: 3016 bytes
Desc: not available
Url : http://porky.devel.redhat.com/pipermail/gui/attachments/20030916/02373ee9/Attr.bin
More information about the GUI
mailing list