Hello, Café.

I am really not fond of web development, but being able to do it in my favorite language is interesting, so I've been spending some time taking a look at happstack.

I decided to start a concrete project so that I could work towards some goal in my learning process, and I have decided on writing an inventory management system for this small computer workshop I work in as a volunteer. We probably have several metric tonnes of various computer equipment; interntal hardware(RAM, hard drives, graphics card, processors and so on) to peripherals and even non-computer related stuff, and it would be good to be able to catalog it and know what exactly we have and so on.

Anyway, my question is about the design itself. My original idea for the database was to create a data type, something like 

data Hardware = 
    Ram 
    { ramType :: RamType
    , ramSize :: Int
    ...
    }

data RamType = SDRAM | DDR | DDR2 | DDR3 .. 

The obvious advantage to this is type safety and thus having an ORM database, so to speak(Please forgive me if my web dev lingo is off here, this is really not my forté).
However, a big disadvantage is that we might want to add new 'type' of hardware to the database and this would require me to stop the server, modify the haskell code to add a new type constructor and so on. 
On top of that, since a graphics card has different attributes than RAM, I will need to dynamically generate the forms required to add new hardware to the database or to search for hardware in the database.

Due to this, I had another idea. I would create a state type that would merely represent groups of items using a map of some kind, where the group name would be a string. Maybe something like this:

data HardwareGroup =
    HardwareGroup
    { groupName :: String
    -- Valid key values for the map
    , groupValues :: [String]
    , groupItems :: [Data.Map String String]
    } 

Which means I can create a new group like this:

type Hardware = [HardwareGroups]

hardwareDatabase :: Hardware
hardwareDatabase = []

newGroup = HardwareGroup "RAM" ["ramSize", "ramSpeed", "ramType", "ramName"] Data.Map.empty

-- Nothing if some value in map isn't a valid part of 
addToGroup :: HardwareGroup -> Data.Map String String -> Maybe HardwareGroup
addToGroup (HardwareGroup name values items) m = 
    case (any (flip notElem values) $ keys m) of
      True -> return Nothing
      _     -> return $ HardwareGroup name values (m : items)

addToGroup newGroup (fromList [("ramSize", "512"), ("ramSpeed", "400 Mhz"), ("ramType", "DDR"), ("ramName", "Kingston")])

The code may not be correct. I wrote it in this email and didn't test it, but I assume you guys get what I'm going for here. 
This will enable me to dynamically generate forms in an easy manner and add to / search in the database, without having to think about some types being strings and some types being ints or something entirely different. 

The reason I've come here asking this question and not some web design mailing list is because I'm writing this in Haskell, and I was wondering if you guys could see some disadvantages to either design that I may not have foreseen, or even come up with other suggestions.

I would just really appreciate any hints, tips, pros or cons to either design. Am I losing something big by sacrificing type safety? Or is the first idea unwieldy enough to justify the sacrifices?

Thanks a lot in advance guys.