Let’s say I have a data type for integer lists. There are two Cons es: one that takes a normal List , and one that takes a DeeperList , which just embeds a List . data DeeperList = DeeperList List data List = Nil | Cons1 Int List | Cons2 Int DeeperList I’d like to write a function incr : incr :: Int -> List -> List such that incr k l increments each integer in l by k plus the number of DeeperList s that embeds that integer. For example: incr 3 $ Cons1 2 $ Cons2 4 $ DeeperList $ Cons2 0 $ DeeperList $ Cons1 5 Nil
-------------------------------------------------------------------
-- represented more compactly as [ 2, 4, D[ 0, D[ 5 ]]]
should be: Cons1 5 $ Cons2 7 $ DeeperList $ Cons2 4 $ DeeperList $ Cons1 10 Nil
-------------------------------------------------------------------
-- [ 5, 7, D[ 4, D[ 10 ]]]
I’d like to implement incr with generics, specifically with something like gfoldl , gmapT , etc., stuff from Data.Data . How do I do that?