/-- Lift a monoid homomorphism that maps polynomials `φ : R[X] →* S[X]`
to a `RatFunc R →* RatFunc S`,
on the condition that `φ` maps non zero divisors to non zero divisors,
by mapping both the numerator and denominator and quotienting them. -/
def map [MonoidHomClass F R[X] S[X]] (φ : F) (hφ : R[X]⁰ ≤ S[X]⁰.comap φ) : RatFunc R →* RatFunc S
    where
  toFun f :=
    RatFunc.liftOn f
      (fun n d => if h : φ d ∈ S[X]⁰ then ofFractionRing (Localization.mk (φ n) ⟨φ d, h⟩) else 0)
      fun {p q p' q'} hq hq' h => by
      dsimp only -- porting note: force the function to be applied
      rw [dif_pos, dif_pos]
      congr 1 -- porting note: this was a `rw [ofFractionRing.inj_eq]` which was overkill anyway
      rw [Localization.mk_eq_mk_iff]
      rotate_left
      · exact hφ hq
      · exact hφ hq'
      refine' Localization.r_of_eq _
      simpa only [map_mul] using congr_arg φ h
  map_one' := by
    dsimp only -- porting note: force the function to be applied
    rw [← ofFractionRing_one, ← Localization.mk_one, liftOn_ofFractionRing_mk, dif_pos]
    · simpa using ofFractionRing_one
    · simpa using Submonoid.one_mem _
  map_mul' x y := by
    dsimp only -- porting note: force the function to be applied
    cases' x with x; cases' y with y
    -- porting note: added `using Localization.rec` (`Localization.induction_on` didn't work)
    induction' x using Localization.rec with p q
    induction' y using Localization.rec with p' q'
    · 

Proof state:
case ofFractionRing.ofFractionRing.f.f
K : Type u
inst✝⁵ : CommRing K
G₀ : Type u_1
L : Type u_2
R : Type u_3
S : Type u_4
F : Type u_5
inst✝⁴ : CommGroupWithZero G₀
inst✝³ : Field L
inst✝² : CommRing R
inst✝¹ : CommRing S
inst✝ : MonoidHomClass F R[X] S[X]
φ : F
hφ : R[X]⁰ ≤ Submonoid.comap φ S[X]⁰
p : R[X]
q : ↥R[X]⁰
p' : R[X]
q' : ↥R[X]⁰
⊢ RatFunc.liftOn ({ toFractionRing := Localization.mk p q } * { toFractionRing := Localization.mk p' q' })
      (fun n d =>
        if h : φ d ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ n) { val := φ d, property := h } } else 0)
      (_ :
        ∀ {p q p' q' : R[X]},
          q ∈ R[X]⁰ →
            q' ∈ R[X]⁰ →
              q' * p = q * p' →
                (if h : φ q ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ p) { val := φ q, property := h } }
                  else 0) =
                  if h : φ q' ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ p') { val := φ q', property := h } }
                  else 0) =
    RatFunc.liftOn { toFractionRing := Localization.mk p q }
        (fun n d =>
          if h : φ d ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ n) { val := φ d, property := h } } else 0)
        (_ :
          ∀ {p q p' q' : R[X]},
            q ∈ R[X]⁰ →
              q' ∈ R[X]⁰ →
                q' * p = q * p' →
                  (if h : φ q ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ p) { val := φ q, property := h } }
                    else 0) =
                    if h : φ q' ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ p') { val := φ q', property := h } }
                    else 0) *
      RatFunc.liftOn { toFractionRing := Localization.mk p' q' }
        (fun n d =>
          if h : φ d ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ n) { val := φ d, property := h } } else 0)
        (_ :
          ∀ {p q p' q' : R[X]},
            q ∈ R[X]⁰ →
              q' ∈ R[X]⁰ →
                q' * p = q * p' →
                  (if h : φ q ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ p) { val := φ q, property := h } }
                    else 0) =
                    if h : φ q' ∈ S[X]⁰ then { toFractionRing := Localization.mk (φ p') { val := φ q', property := h } }
                    else 0)

Next tactic:
have hq : φ q ∈ S[X]⁰ := hφ q.prop