¿Cómo puedo recuperar el compartir en un GADT?

EnTipo-Compartir observable seguro en Haskell Andy Gill muestra cómo recuperar el intercambio que existía en el nivel de Haskell, en un DSL. Su solución se implementa en elpaquete de datos-reificación. ¿Se puede modificar este enfoque para trabajar con GADTs? Por ejemplo, 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

Me gustaría recuperar el intercambio transformando el AST anterior a

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

por la forma de una función

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

(No estoy seguro sobre el tipo derecoverSharing.)

Tenga en cuenta que no me importa la introducción de nuevos enlaces a través de una construcción let, sino solo en la recuperación del uso compartido que existía en el nivel de Haskell. Por eso tengorecoverSharing devolver unMap.

Si no se puede hacer como un paquete reutilizable, ¿se puede hacer al menos para GADT específico?