Generics for constructing Rows

Hi, all. I've come into trouble defining function `gmap` which will work on these data types:
data Row = Row (E Name) (E Salary) (E Department)
type E a = Either (Maybe RowIndex) (Maybe a)
type RowIndex = Int
`RowIndex`, `Name`, `Salary`, `Department` have kind * pseudocode:
gmap :: (E a -> E a) -> Row -> Row
readRow :: [String] -> Row -> Row readRow l = gmap (\(Left (Just ri)) -> Right $ l `atMay` c >>= readMay)
`atMay` and `readMay` are defined in module `Safe` from package `safe`
atMay :: [a] -> Int -> Maybe a readMay :: (Read a) => String -> Maybe a
Basically we have optional Row indices and try to read raw row (list of Strings) into the same Row type if index is present. At this moment I just have separate data type for row which has been read and just a list of row indices, but it is definitely flawed when I need to add fields to Row from time to time, as it is too easy to introduce bugs while positioning in list of row indices, not mentioning all those boilerplate code flowing around. I've tried to define gmap using libraries for generic programming but failed each time while type checking for different reasons. With `Data.Generics` and `gmapT` it fails because gmapT doesn't allow traversion function to have `Read a` constraint (Data and Typeable instances for Row and inner data types of course were derived). EMGM's map demands traversion function to be non-polymorphic, i.e. type-checker fails with the message, complaining it cannot match `E a` against `E Name`, against `E Salary` etc. For each of this I've spent smth about five hours just reading API docs, papers, and trying to beat type-checker. Maybe I'll look into Smash, RepLib and others, but I hope someone was also trying to define such gmap and succeeded. So, generic programming folks, is it even possible to define such function? I don't really care about using GHC extensions, I don't care about code being portable, I just want to remove boilerplate and prevent introducing bugs. Thanks in advance, Max.
participants (1)
-
Max Desyatov