rewrite with GADTs