AW: container for different types, avoiding boiler plate

oleg@pobox.com oleg@pobox.com
Fri, 22 Aug 2003 11:57:15 -0700 (PDT)


> > There is no need for Maybe. In fact, if you attempt to fetch
> > a type that you didn't put into the attrs, you get a _compile-time_
> > error.

> But I'm not sure if it's suitable for what I'm doing, as the attributes
> get inserted at run time, and not all of them appear everywhere. So
> Maybe is quite natural here.

The question then becomes: are the types of all attributes that might
appear in the list attrs are known at the compile time? If so, the
previous solution applies as it is, still retaining the static type
guarantees: unlike the solution involving Dynamics, an attempt
to fetch a value of the type not present among the "attributable"
types is a type error.

Using the constant code in the Appendix of the previous message, we
can write

> data Gender = Masc | Fem | Neutr   deriving (Show)
> data Number = First | Second | Third deriving (Show)
> data Color = Color {redval, greenval, blueval:: Int} deriving Show

Define all types that may appear in attributes. An attempt to place or
fetch some other type from init_attrs (or its altered variant) will be
a compile-time error.

> init_attrs = Cons (Nothing::Maybe Gender) $ 
>              Cons (Nothing::Maybe Number) $
>              Cons (Nothing::Maybe Color)  $ 
>              Nil

First we insert the values of some attributes at the run time (in the
let expression), and then retrieve them. We can insert and retrieve
the values in any order we wish. We can even delete values by
inserting Nothing cast to appropriate type.

> test :: (Maybe Color, Maybe Number, Maybe Gender) =
>   let attrs = alter (Just Masc) $
>               alter (Just (Color 0 0 255)) $
>               init_attrs
>   in (fetch undefined attrs, fetch undefined attrs,
>       fetch undefined attrs)


*Main> test
(Just (Color {redval = 0, greenval = 0, blueval = 255}),Nothing,Just Masc)