[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