letR :: (Monad m)
  => Rewrite m [C.CoreContext] C.Term
  -> Rewrite m [C.CoreContext] C.Term
  -> Rewrite m [C.CoreContext] C.Term
letR rr1 rr2 = transparently $ rewrite $ \e -> case e of
  (C.LetRec binds e) -> do let bndrs = map fst binds
                           liftM2 C.LetRec (mapM (secondM (apply (C.LetBinding bndrs) rr1)) binds)
                                           (apply (C.LetBody bndrs) rr2 e)
  _                  -> fail "letR"
letR :: (Monad m)
  => Rewrite m [C.CoreContext] C.Term
  -> Rewrite m [C.CoreContext] C.Term
  -> Rewrite m [C.CoreContext] C.Term
letR rr1 rr2 = transparently $ rewrite $ \e -> case e of
  (C.LetRec binds e) -> do let bndrs = map fst binds
                           liftM2 C.LetRec (mapM (secondM (apply (C.LetBinding bndrs) rr1)) binds)
                                           (apply (C.LetBody bndrs) rr2 e)
  _                  -> fail "letR"
letR rr1 rr2 = transparently $ rewrite $ \e -> case e of
  (C.LetRec binds e) -> do let bndrs = map fst binds
                           liftM2 C.LetRec (mapM (secondM (apply (C.LetBinding bndrs) rr1)) binds)
                                           (apply (C.LetBody bndrs) rr2 e)
  _                  -> fail "letR"