I'm looking for pointers on how to do something.  What I'm trying to do: I want to define a newtype wrapper for database connections with a phantom type to control whether the connection is read-only or read-write.  So I have:
    newtype Conn a = Conn { unConn :: Connection }
    data ReadOnly = ReadOnly
    data ReadWrite = ReadWrite
    -- Simplifying here
    openConn :: MonadIO m => a -> Conn a
    query :: (MonadIO m, ToRow r, FromRow s) => Conn a -> Query -> r -> m [s]
    execute :: (MonadIO m, ToRow r) => Conn a -> Query -> r -> m Int64
But I want to be able to restrict the type a to be either ReadOnly or ReadWrite.  Solutions I've come up with so far are:
- Don't bother.  Later function calls put enough of constraint on the types that it isn't really necessary.  Or rather, ReadWrite is necessary, but ReadOnly isn't.
- Define some type class that ReadWrite and ReadOnly implement, but don't export the body of the typeclass from the module, preventing other people from implementing it for other types.
- Some sort of trickiness with closed type families that I haven't worked out yet.
Are their alternatives I haven't considered yet?
Thanks.
Brian