Andrew Sneap, 26 November 2021

In this file, I define addition of integers, and prove some common
properties of multiplication.

\begin{code}

{-# OPTIONS --safe --without-K #-}

open import MLTT.Spartan renaming (_+_ to _∔_)

open import Naturals.Addition renaming (_+_ to _ℕ+_)
open import Naturals.Multiplication renaming (_*_ to _ℕ*_)
open import Naturals.Properties
open import Integers.Type
open import Integers.Addition
open import Integers.Negation

module Integers.Multiplication where

\end{code}

Instead of defining auxilliary functions with a natural number
argument, multiplication is defined by pattern matching.

\begin{code}

_*_ :     
x * pos 0            = pos 0
x * pos (succ y)     = x + (x * pos y)
x * negsucc 0        = - x
x * negsucc (succ y) = (- x) + (x * negsucc y)

infixl 32 _*_

pos-multiplication-equiv-to-ℕ : (x y : )  pos x * pos y  pos (x ℕ* y)
pos-multiplication-equiv-to-ℕ x = ℕ-induction base step
  where
    base : pos x * pos 0  pos (x ℕ* 0)
    base = refl

    step : (k : )
          pos x * pos k  pos (x ℕ* k)
          pos x * pos (succ k)  pos (x ℕ* succ k)
    step k IH = pos x * pos (succ k) =⟨ ap (pos x +_) IH                       
                pos x + pos (x ℕ* k) =⟨ distributivity-pos-addition x (x ℕ* k) 
                pos (x ℕ* succ k)    


\end{code}

The following proofs that 0 is the base and 1 is the identity for
multiplication exemplify the "induction on both positives and
negatives" strategy.

To choose a specific example, the left identity element of multiplication is 1.
The two bases cases are 0 and -1, and definitionally we have that 1 * 0 = 0, and
1 * (- 1) = (- 1).

Induction on positives:
 1 * pos (succ x) = 1 + 1 * pos x (by definition)
                  = 1 + pos x     (by applying (_+ 1) to the IH)
                  = pos (succ x)  (by commutativity of addition).

Induction on negatives:
 1 * negsucc (succ x) = (- 1) + 1 * negsucc x (by definition)
                      = (- 1) + negsucc x     (by applying (_- 1) to the IH)
                      = negsucc (succ x)      (by  commutativity of addition).
\begin{code}

ℤ-zero-right-is-zero : (x : )  x * pos 0  pos 0
ℤ-zero-right-is-zero x = refl

ℤ-zero-left-base : (x : )  pos 0 * x  pos 0
ℤ-zero-left-base (pos 0) = refl
ℤ-zero-left-base (pos (succ x)) =
 pos 0 * pos (succ x) =⟨ ℤ-zero-left-neutral (pos 0 * pos x) 
 pos 0 * pos x        =⟨ ℤ-zero-left-base (pos x)            
 pos 0                
ℤ-zero-left-base (negsucc 0) = refl
ℤ-zero-left-base (negsucc (succ x)) =
 pos 0 * negsucc (succ x) =⟨ ℤ-zero-left-neutral (pos 0 * negsucc x) 
 pos 0 * negsucc x        =⟨ ℤ-zero-left-base (negsucc x)            
 pos 0 

ℤ-mult-right-id : (x : )  x * pos 1  x
ℤ-mult-right-id x = refl

ℤ-mult-left-id : (x : )  pos 1 * x  x
ℤ-mult-left-id (pos 0) = refl
ℤ-mult-left-id (pos (succ x)) =
 pos 1 * pos (succ x)  =⟨ ℤ+-comm (pos 1) (pos 1 * pos x)   
 pos 1 * pos x + pos 1 =⟨ ap succℤ (ℤ-mult-left-id (pos x)) 
 succℤ (pos x)         
ℤ-mult-left-id (negsucc 0) = refl
ℤ-mult-left-id (negsucc (succ x)) =
 pos 1 * negsucc (succ x)      =⟨ ℤ+-comm (negsucc 0) (pos 1 * negsucc x) 
 pos 1 * negsucc x + negsucc 0 =⟨ ap predℤ (ℤ-mult-left-id (negsucc x))   
 predℤ (negsucc x)             

\end{code}

Now we have an example where the positive and negative inductions are separated
into subfunctions, for readibility, since the individual proofs are
lengthy. Distributivity of addition relies on commutativity and associativity
(and distributivity of negation).

\begin{code}

distributivity-mult-ℤ₀ : (x y : ) (z : )
                             (x + y) * pos z  x * pos z + y * pos z
distributivity-mult-ℤ₀ x y = ℕ-induction base step
 where
  base : (x + y) * pos 0  x * pos 0 + y * pos 0
  base = refl

  step : (k : )
        (x + y) * pos k  x * pos k + y * pos k
        (x + y) * pos (succ k)  x * pos (succ k) + y * pos (succ k)
  step k IH = (x + y) * pos (succ k)              =⟨ i    
              (x + y) + (u + w)                   =⟨ ii   
              (x + y) + u + w                     =⟨ iii  
              x + (y + u) + w                     =⟨ iv   
              x + (u + y) + w                     =⟨ v    
              x + u + y + w                       =⟨ vi   
              x + u + (y + w)                     =⟨ refl 
              x * pos (succ k) + y * pos (succ k) 
     where
       u w : 
       u = x * pos k
       w = y * pos k
       i   = ap ((x + y) +_) IH
       ii  = ℤ+-assoc (x + y) u w ⁻¹
       iii = ap (_+ w) (ℤ+-assoc x y u)
       iv  = ap  z  (x + z) + w) (ℤ+-comm y u)
       v   = ap (_+ w) (ℤ+-assoc x u y ⁻¹)
       vi  = ℤ+-assoc (x + u) y w

distributivity-mult-ℤ₁ : (x y : )  (z : )
                        (x + y) * negsucc z  x * negsucc z + y * negsucc z
distributivity-mult-ℤ₁ x y = ℕ-induction base step
 where
  base : (x + y) * negsucc 0  x * negsucc 0 + y * negsucc 0
  base = (x + y) * negsucc 0           =⟨ refl                  
         - (x + y)                     =⟨ negation-dist x y ⁻¹  
         (- x) + (- y)                 =⟨ refl                  
         x * negsucc 0 + y * negsucc 0 

  step : (k : )
        (x + y) * negsucc k                x * negsucc k + y * negsucc k
        (- (x + y)) + (x + y) * negsucc k  (- x) + x * negsucc k + ((- y) + y * negsucc k)
  step k IH = (- (x + y)) + (x + y) * negsucc k               =⟨ i    
              (- (x + y)) + (u + w)                           =⟨ ii   
              (- x) - y + (u + w)                             =⟨ iii  
              (- x) + ((- y) + (u + w))                       =⟨ iv   
              (- x) + ((- y) + u + w)                         =⟨ v    
              (- x) + (u - y + w)                             =⟨ vi   
              (- x) + (u + ((- y) + w))                       =⟨ vii  
              (- x) + u + ((- y) + w)                         =⟨ refl 
              (- x) + x * negsucc k + ((- y) + y * negsucc k) 
    where
      u w : 
      u   = x * negsucc k
      w   = y * negsucc k
      i   = ap ((- (x + y)) +_) IH
      ii  = ap (_+ ((u + w))) (negation-dist x y ⁻¹)
      iii = ℤ+-assoc (- x) (- y) (u + w)
      iv  = ap ((- x) +_) (ℤ+-assoc (- y) u w ⁻¹)
      v   = ap  z  (- x) + (z + w)) (ℤ+-comm (- y) u)
      vi  = ap ((- x) +_) (ℤ+-assoc u (- y) w)
      vii = ℤ+-assoc (- x) u ((- y) + w) ⁻¹

distributivity-mult-over-ℤ : (x y z : )  (x + y) * z  (x * z) + (y * z)
distributivity-mult-over-ℤ x y (pos z)     = distributivity-mult-ℤ₀ x y z
distributivity-mult-over-ℤ x y (negsucc z) = distributivity-mult-ℤ₁ x y z

\end{code}

Following the same strategy as distributivity, we have proofs that
relate multiplication and negation, commutativity of integers, and how
negation distributes over multiplication.

\begin{code}

mult-negation : (x : )  - x  negsucc 0 * x
mult-negation = ℤ-induction base step₁ step₂
 where
  base : - pos 0  negsucc 0 * pos 0
  base = refl

  step₁ : (k : )
         - k        negsucc 0 * k
         - succℤ k  negsucc 0 * succℤ k
  step₁ (pos 0)            IH = refl
  step₁ (pos (succ x))     IH
   = predℤ (negsucc x)                =⟨ i  
     predℤ (negsucc 0 * pos (succ x)) =⟨ ii 
     negsucc 0 * succℤ (pos (succ x)) 
   where
    i  = ap predℤ IH
    ii = ℤ-pred-is-minus-one (negsucc 0 * pos (succ x))
  step₁ (negsucc 0)        IH = refl
  step₁ (negsucc (succ x)) IH =
   ℤ+-lc (- succℤ (negsucc (succ x)))
          (negsucc 0 * succℤ (negsucc (succ x))) (pos 1) I
   where
    I : pos 1 + (- succℤ (negsucc (succ x)))  pos 1 + negsucc 0 * succℤ (negsucc (succ x))
    I = pos 1 + (- succℤ (negsucc (succ x))) =⟨ i  
        succℤ (pos x + pos 1)                =⟨ IH 
        negsucc 0 * negsucc (succ x)         
     where
      i = ap succℤ (ℤ+-comm (pos 1) (pos x))

  step₂ : (k : )
         - succℤ k  negsucc 0 * succℤ k
         - k        negsucc 0 * k
  step₂ (pos 0)        IH = refl
  step₂ (pos (succ x)) IH = ℤ+-lc (- pos (succ x))
                                   (negsucc 0 * pos (succ x))
                                    (negsucc 0) I
   where
    I : negsucc 0 - pos (succ x)  negsucc 0 * pos (succ (succ x))
    I = negsucc 0 - pos (succ x)         =⟨ ℤ+-comm (negsucc 0) (negsucc x) 
        negsucc x + negsucc 0            =⟨ IH                              
        negsucc 0 * succℤ (pos (succ x)) 
  step₂ (negsucc 0)        IH = refl
  step₂ (negsucc (succ x)) IH = I
   where
    I : pos (succ x) + pos 1  pos 1 + negsucc 0 * succℤ (negsucc (succ x))
    I = pos (succ x) + pos 1                         =⟨ i  
        pos 1 + pos (succ x)                         =⟨ ii 
        pos 1 + negsucc 0 * succℤ (negsucc (succ x)) 
     where
      i  = ℤ+-comm (pos (succ x)) (pos 1)
      ii = ap (pos (succ 0) +_) IH

ℤ*-comm₀ : (x : )  (y : )  x * pos y  pos y * x
ℤ*-comm₀ x = ℕ-induction base step
 where
  base : x * pos 0  pos 0 * x
  base = x * pos 0 =⟨ ℤ-zero-left-base x ⁻¹ 
         pos 0 * x 

  step : (k : )
        x * pos k  pos k * x
        x * pos (succ k)  (pos k + pos 1) * x
  step k IH = x + x * pos k         =⟨ i   
              x + pos k * x         =⟨ ii  
              pos 1 * x + pos k * x =⟨ iii 
              (pos 1 + pos k) * x   =⟨ iv  
              (pos k + pos 1) * x   
   where
    i   = ap (x +_) IH
    ii  = ap (_+ (pos k * x)) (ℤ-mult-left-id x ⁻¹)
    iii = distributivity-mult-over-ℤ (pos 1) (pos k) x ⁻¹
    iv  = ap (_* x) (ℤ+-comm (pos 1) (pos k))

ℤ*-comm₁ : (x : )  (y : )  x * negsucc y  negsucc y * x
ℤ*-comm₁ x = ℕ-induction base step
 where
  base : x * negsucc 0  negsucc 0 * x
  base = mult-negation x

  step : (k : )
        x * negsucc k         negsucc k * x
        x * negsucc (succ k)  negsucc (succ k) * x
  step k IH = x * negsucc (succ k)             =⟨ refl 
              (- x) + x * negsucc k            =⟨ i    
              (- x) + negsucc k * x            =⟨ ii   
              negsucc 0 * x + negsucc k * x    =⟨ iii  
              (negsucc 0 + negsucc k) * x      =⟨ iv   
              negsucc (succ k) * x             
   where
    i   = ap ((- x) +_) IH
    ii  = ap (_+ (negsucc k * x)) (mult-negation x)
    iii = distributivity-mult-over-ℤ (negsucc 0) (negsucc k) x ⁻¹
    iv  = ap (_* x) (ℤ+-comm (negsucc 0) (negsucc k))

ℤ*-comm : (x y : )  x * y  y * x
ℤ*-comm x (pos y)     = ℤ*-comm₀ x y
ℤ*-comm x (negsucc y) = ℤ*-comm₁ x y

distributivity-mult-over-ℤ' : (x y z : )  z * (x + y)  z * x + z * y
distributivity-mult-over-ℤ' x y z = γ
 where
  γ : z * (x + y)  z * x + z * y
  γ = z * (x + y)      =⟨ ℤ*-comm z (x + y)                 
      (x + y) * z      =⟨ distributivity-mult-over-ℤ x y z  
      x * z + y * z    =⟨ ap (_+ (y * z)) (ℤ*-comm x z)     
      z * x + y * z    =⟨ ap ((z * x) +_ ) (ℤ*-comm y z)    
      z * x + z * y    


negation-dist-over-mult₀ : (x : )  (y : )  x * (- pos y)  - x * pos y
negation-dist-over-mult₀ x = ℕ-induction base step
  where
    base : x * (- pos 0)  - (x * pos 0)
    base = refl

    step : (k : )
          x * (- pos k)         - (x * pos k)
          x * (- pos (succ k))  - (x * pos (succ k))
    step 0        IH = refl
    step (succ k) IH = x * (- pos (succ (succ k)))  =⟨ i  
                       (- x) + (- x * pos (succ k)) =⟨ ii 
                       - (x + (x + x * pos k))      
     where
      i  = ap ((- x) +_) IH
      ii = negation-dist x (x + (x * pos k))

negation-dist-over-mult₁ : (x : )  (y : )
                          x * (- negsucc y)  - x * negsucc y
negation-dist-over-mult₁ x = ℕ-induction base step
 where
  base : x * (- negsucc 0)  - x * negsucc 0
  base = minus-minus-is-plus x ⁻¹

  step : (k : )
        x * (- negsucc k)  - x * negsucc k
        x + x * (- negsucc k)  - ((- x) + x * negsucc k)
  step k IH = x + x * (- negsucc k)         =⟨ i   
              x + (- x * negsucc k)         =⟨ ii  
              (- (- x)) + (- x * negsucc k) =⟨ iii 
              - ((- x) + x * negsucc k)     
   where
    i   = ap (x +_) IH
    ii  = ap (_+ (- (x * negsucc k)) ) (minus-minus-is-plus x ⁻¹)
    iii = negation-dist (- x) (x * negsucc k)

negation-dist-over-mult : (x y : )  x * (- y)  - (x * y)
negation-dist-over-mult x (pos y)     = negation-dist-over-mult₀ x y
negation-dist-over-mult x (negsucc y) = negation-dist-over-mult₁ x y

negation-dist-over-mult' : (x y : )  (- x) * y  - (x * y)
negation-dist-over-mult' x y = II
 where
  I : y * (- x)  - (y * x)
  I = negation-dist-over-mult y x

  II : (- x) * y  - x * y
  II = (- x) * y =⟨ ℤ*-comm (- x) y     
       y * (- x) =⟨ I                   
       - (y * x) =⟨ ap -_ (ℤ*-comm y x) 
       - (x * y) 

minus-times-minus-is-positive : (x y : )  (- x) * (- y)  x * y
minus-times-minus-is-positive x y = γ
 where
  γ : (- x) * (- y)  x * y
  γ = (- x) * (- y) =⟨ negation-dist-over-mult' x (- y)    
      - (x * (- y)) =⟨ ap -_ (negation-dist-over-mult x y) 
      - (- (x * y)) =⟨ minus-minus-is-plus (x * y)         
      x * y         

ℤ*-assoc₀ : (x y : )  (z :  )  x * (y * pos z)  x * y * pos z
ℤ*-assoc₀ x y = ℕ-induction base step
  where
    base : x * (y * pos 0)  x * y * pos 0
    base = refl

    step : (k : )
          x * (y * pos k)          x * y * pos k
          x * (y * pos (succ k))   x * y * pos (succ k)
    step k IH = x * (y * pos (succ k))        =⟨ i  
                x * y + x * (y * pos k)       =⟨ ii 
                x * y + x * y * pos k         
     where
      i  = distributivity-mult-over-ℤ' y (y * pos k) x
      ii = ap ((x * y) +_) IH

ℤ*-assoc₁ : (x y : )  (z : )  x * (y * negsucc z)  x * y * negsucc z
ℤ*-assoc₁ x y = ℕ-induction base step
 where
  base : x * (y * negsucc 0)  x * y * negsucc 0
  base = negation-dist-over-mult x y

  step : (k : )
        x * (y * negsucc k)  x * y * negsucc k
        x * (y * negsucc (succ k))  x * y * negsucc (succ k)
  step k IH = x * (y * negsucc (succ k))        =⟨ i   
              x * (- y) + x * (y * negsucc k)   =⟨ ii  
              x * (- y) + x * y * negsucc k     =⟨ iii 
              (- x * y) + x * y * negsucc k     
   where
    i   = distributivity-mult-over-ℤ' (- y) (y * negsucc k) x
    ii  = ap ((x * (- y)) +_) IH
    iii = ap (_+ ((x * y) * negsucc k)) (negation-dist-over-mult x y)

ℤ*-assoc : (x y z : )  x * y * z  x * (y * z)
ℤ*-assoc x y (pos z)     = ℤ*-assoc₀ x y z ⁻¹
ℤ*-assoc x y (negsucc z) = ℤ*-assoc₁ x y z ⁻¹

is-pos-succ-addition : (x y : )
                      is-pos-succ x
                      is-pos-succ y
                      is-pos-succ (x + y)
is-pos-succ-addition x (negsucc y)           x>0 y>0 = 𝟘-elim y>0
is-pos-succ-addition x (pos 0)               x>0 y>0 = 𝟘-elim y>0
is-pos-succ-addition x (pos (succ 0))        x>0 y>0 = is-pos-succ-succℤ x x>0
is-pos-succ-addition x (pos (succ (succ y))) x>0 y>0 =
 is-pos-succ-succℤ
  (x + pos (succ y))
   (is-pos-succ-addition x (pos (succ y)) x>0 y>0)

is-pos-succ-mult : (x y : )
                  is-pos-succ x
                  is-pos-succ y
                  is-pos-succ (x * y)
is-pos-succ-mult x (negsucc y)           x>0 y>0 = 𝟘-elim y>0
is-pos-succ-mult x (pos 0)               x>0 y>0 = 𝟘-elim y>0
is-pos-succ-mult x (pos (succ 0))        x>0 y>0 = x>0
is-pos-succ-mult x (pos (succ (succ y))) x>0 y>0 =
 is-pos-succ-addition x (x * pos (succ y)) x>0
  (is-pos-succ-mult x (pos (succ y)) x>0 y>0)

pos-times-negative : (n k : )  Σ m   , pos (succ n) * negsucc k  negsucc m
pos-times-negative n 0        = n , refl
pos-times-negative n (succ k) = I IH
 where
  IH : Σ m   , pos (succ n) * negsucc k  negsucc m
  IH = pos-times-negative n k
  I : Σ m   , pos (succ n) * negsucc k  negsucc m
     Σ m   , pos (succ n) * negsucc (succ k)  negsucc m
  I (m , e) = succ n ℕ+ m , II
   where
    II : pos (succ n) * negsucc (succ k)  negsucc (succ n ℕ+ m)
    II = pos (succ n) * negsucc (succ k)      =⟨ refl 
         negsucc n + pos (succ n) * negsucc k =⟨ i    
         negsucc n + negsucc m                =⟨ ii   
         - (succℤ (pos (succ n) + pos m))     =⟨ iii  
         - succℤ (pos (succ n ℕ+ m))          =⟨ refl 
         negsucc (succ n ℕ+ m)                
     where
      i   = ap (negsucc n +_) e
      ii  = negation-dist (pos (succ n)) (pos (succ m))
      iii = ap  z  - (succℤ z)) (distributivity-pos-addition (succ n) m)

negatives-equal : (x y : )  (- x)  (- y)  x  y
negatives-equal x y e = I
 where
  I : x  y
  I = x       =⟨ minus-minus-is-plus x ⁻¹ 
      - (- x) =⟨ ap -_ e                  
      - (- y) =⟨ minus-minus-is-plus y    
      y       

ppnnp-lemma : (a b : )  Σ c   , negsucc a + negsucc b  negsucc c
ppnnp-lemma a = ℕ-induction base step
 where
  base : Σ c   , negsucc a + negsucc 0  negsucc c
  base = succ a , refl

  step : (k : )  Σ c   , negsucc a + negsucc k  negsucc c
                  Σ c   , negsucc a + negsucc (succ k)  negsucc c
  step k (c , IH) = succ c , ap predℤ IH

product-positive-negative-not-positive : (a b c : )
                                        ¬ (pos a * negsucc b  pos (succ c))
product-positive-negative-not-positive 0 0 c e = 𝟘-elim (positive-not-zero c I)
 where
  I : succ c  0
  I = pos-lc e ⁻¹
product-positive-negative-not-positive 0 (succ b) c e = 𝟘-elim II
 where
  I : pos 0  pos (succ c)
  I = pos 0                     =⟨ ℤ-zero-left-base (negsucc (succ b)) ⁻¹ 
      pos 0 * negsucc (succ b)  =⟨ e                                      
      pos (succ c)              

  II : 𝟘
  II = positive-not-zero c (pos-lc I ⁻¹)
product-positive-negative-not-positive (succ a) (succ b) c e₁ = γ I
 where
  I : Σ z   , succ z  succ a ℕ* succ b
  I = pos-mult-is-succ a b

  γ : ¬ (Σ z   , succ z  succ a ℕ* succ b)
  γ (z , e₂) = γ' II
   where
    II : Σ d    , negsucc a + negsucc z  negsucc d
    II = ppnnp-lemma a z

    γ' : ¬ (Σ d   , negsucc a + negsucc z  negsucc d)
    γ' (d , e₃) = negsucc-not-pos IV
     where
      III : negsucc z  pos (succ a) * negsucc b
      III = negsucc z                     =⟨ refl 
            - pos (succ z)                =⟨ i    
            - pos (succ a ℕ* succ b)      =⟨ ii   
            - pos (succ a) * pos (succ b) =⟨ iii  
            pos (succ a) * negsucc b      
       where
        i   = ap  α  -_ (pos α)) e₂
        ii  = ap -_ (pos-multiplication-equiv-to-ℕ (succ a) (succ b)) ⁻¹
        iii =  negation-dist-over-mult (pos (succ a)) (pos (succ b)) ⁻¹

      IV : negsucc d  pos (succ c)
      IV = negsucc d                            =⟨ e₃ ⁻¹                 
           negsucc a + negsucc z                =⟨ ap (negsucc a +_) III 
           negsucc a + pos (succ a) * negsucc b =⟨ refl                  
           pos (succ a) * negsucc (succ b)      =⟨ e₁                    
           pos (succ c)                         

\end{code}

Finally, we have equivalences of various re-arrangements of
multiplication of integers, which can be useful to reduce the size of
larger proofs.

\begin{code}

ℤ-mult-rearrangement : (x y z : )  x * y * z  x * z * y
ℤ-mult-rearrangement x y z = x * y * z   =⟨ ℤ*-assoc x y z          
                             x * (y * z) =⟨ ap (x *_) (ℤ*-comm y z) 
                             x * (z * y) =⟨ ℤ*-assoc x z y ⁻¹       
                             x * z * y   

ℤ-mult-rearrangement' : (x y z : )  z * (x * y)  y * (x * z)
ℤ-mult-rearrangement' x y z = z * (x * y) =⟨ ℤ*-comm z (x * y)          
                              x * y * z   =⟨ ℤ-mult-rearrangement x y z 
                              x * z * y   =⟨ ℤ*-comm (x * z) y          
                              y * (x * z) 

ℤ-mult-rearrangement'' : (w x y z : )  x * y * (w * z)  w * y * (x * z)
ℤ-mult-rearrangement'' w x y z = γ
 where
  γ : x * y * (w * z)  w * y * (x * z)
  γ = x * y * (w * z)     =⟨ ℤ-mult-rearrangement x y (w * z)     
      x * (w * z) * y     =⟨ ap (_* y) (ℤ*-assoc x w z ⁻¹)        
      x * w * z * y       =⟨ ap  a  (a * z) * y) (ℤ*-comm x w) 
      w * x * z * y       =⟨ ℤ*-assoc (w * x) z y                 
      w * x * (z * y)     =⟨ ap ((w * x) *_) (ℤ*-comm z y)        
      w * x * (y * z)     =⟨ ℤ*-assoc (w * x) y z ⁻¹              
      w * x * y * z       =⟨ ap (_* z) (ℤ*-assoc w x y )          
      w * (x * y) * z     =⟨ ap  a  (w * a) * z) (ℤ*-comm x y) 
      w * (y * x) * z     =⟨ ap (_* z) (ℤ*-assoc w y x ⁻¹)        
      w * y * x * z       =⟨ ℤ*-assoc (w * y) x z                 
      w * y * (x * z)     

ℤ-mult-rearrangement''' : (x y z : )  x * (y * z)  y * (x * z)
ℤ-mult-rearrangement''' x y z = x * (y * z) =⟨ ℤ*-assoc x y z ⁻¹       
                                x * y * z   =⟨ ap (_* z) (ℤ*-comm x y) 
                                y * x * z   =⟨ ℤ*-assoc y x z          
                                y * (x * z) 

\end{code}