[Haskell-cafe] Generics for constructing Rows

Max Desyatov explicitcall at googlemail.com
Thu Aug 20 05:46:31 EDT 2009

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 *


> 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.

More information about the Haskell-Cafe mailing list