Yes, but like any encoding, it has its problems. One potential issue is that you will need to formulate your transformations as strict catamorphisms (folds), e.g. you cannot match two levels deep. This has reasoning advantages, but makes it harder for the average user. Type classes can also have issues with ambiguities, if many type variables are involved. Lastly, you also cannot match all remaining terms, like these examples:
getDates
:: Exp
-> Set Date
getDates = cata alg where
alg :: ExpF (Set Date) -> Set Date
alg (EDate i) = S.singleton i
alg e = fold e
substitute
:: Map VarId (ExpF Exp)
-> Exp
-> Exp
substitute env = cata alg where
alg :: ExpF Exp -> Exp
alg (EVar i)
| Just e <-M.lookup i env = Fix e
alg e = Fix e