haskellscrap-your-boilerplaterank-n-types

How to use Data.Data?


As I'm not familiar with rank-N types, the type signature of gfoldl is a troublesome for me:

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> a
-> c a

The only functions I can think of are \xs y -> ($y) <$> xs and pure, respectively.

Other functions such as gunfold and gmapT have similar problems. So what are notable examples of nontrivial uses of them?


Solution

  • For the gmapT case the mkT function is defined for this purpose in the original paper.

    mkT :: (Typeable a, Typeable b ) => (b -> b) -> a -> a
    mkT f = fromMaybe id (cast f)
    

    For example to increment all int fields in the A, you can write something like

    data A = A {f :: Int, s :: Int} deriving (Data, Typeable)
    
    ex = gmapT (mkT inc) (A 2 3) where 
      inc :: Int -> Int
      inc = (+1)
    

    To make it clearer the ex function can be written like this too:

    ex2 = gmapT f (A 2 3) where 
      f :: (Data a ) =>  a -> a
      f a = case cast a of 
        Nothing -> a
        (Just (b :: Int)) -> fromJust $ cast (b + 1)