Como posso recuperar o compartilhamento em um GADT?

EmCompartilhamento observável de tipo seguro em Haskell Andy Gill mostra como recuperar o compartilhamento que existia no nível Haskell, em uma DSL. Sua solução é implementada nopacote de reificação de dados. Essa abordagem pode ser modificada para funcionar com os GADTs? Por exemplo, dado este GADT:

data Ast e where
  IntLit :: Int -> Ast Int
  Add :: Ast Int -> Ast Int -> Ast Int
  BoolLit :: Bool -> Ast Bool
  IfThenElse :: Ast Bool -> Ast e -> Ast e -> Ast e

Gostaria de recuperar o compartilhamento, transformando a AST acima em

type Name = Unique

data Ast2 e where
  IntLit2 :: Int -> Ast2 Int
  Add2 :: Ast2 Int -> Ast2 Int -> Ast2 Int
  BoolLit2 :: Bool -> Ast2 Bool
  IfThenElse2 :: Ast2 Bool -> Ast2 e -> Ast2 e -> Ast2 e
  Var :: Name -> Ast2 e

a propósito de uma função

recoverSharing :: Ast -> (Map Name, Ast2 e1, Ast2 e2)

(Eu não tenho certeza sobre o tipo derecoverSharing.)

Note que eu não me importo em introduzir novas ligações através de uma construção let, mas apenas em recuperar o compartilhamento que existia no nível Haskell. É por isso que tenhorecoverSharing devolver umMap.

Se não puder ser feito como um pacote reutilizável, pelo menos pode ser feito para um GADT específico?