reduce :: RE -> RE
reduce r = if go r == r then r else reduce (go r)
    where go (Plus Empty Empty) = Empty
          go (Plus a Empty) = go a
          go (Plus Empty b) = go b
          go (Plus a b) = Plus (go a) (go b)
          go (Concat Empty _) = Empty
          go (Concat _ Empty) = Empty
          go (Concat Epsilon Epsilon) = Epsilon
          go (Concat a Epsilon) = go a
          go (Concat Epsilon b) = go b
          go (Concat a b) = Concat (go a) (go b)
          go (Closure Empty) = Empty
          go (Closure Epsilon) = Epsilon
          go (Closure k) = Closure (go k)
          go (Single k) = Single k
          go Epsilon = Epsilon
          go Empty = Empty
reduce :: RE -> RE
reduce r = if go r == r then r else reduce (go r)
    where go (Plus Empty Empty) = Empty
          go (Plus a Empty) = go a
          go (Plus Empty b) = go b
          go (Plus a b) = Plus (go a) (go b)
          go (Concat Empty _) = Empty
          go (Concat _ Empty) = Empty
          go (Concat Epsilon Epsilon) = Epsilon
          go (Concat a Epsilon) = go a
          go (Concat Epsilon b) = go b
          go (Concat a b) = Concat (go a) (go b)
          go (Closure Empty) = Empty
          go (Closure Epsilon) = Epsilon
          go (Closure k) = Closure (go k)
          go (Single k) = Single k
          go Epsilon = Epsilon
          go Empty = Empty
reduce r = if go r == r then r else reduce (go r)
    where go (Plus Empty Empty) = Empty
          go (Plus a Empty) = go a
          go (Plus Empty b) = go b
          go (Plus a b) = Plus (go a) (go b)
          go (Concat Empty _) = Empty
          go (Concat _ Empty) = Empty
          go (Concat Epsilon Epsilon) = Epsilon
          go (Concat a Epsilon) = go a
          go (Concat Epsilon b) = go b
          go (Concat a b) = Concat (go a) (go b)
          go (Closure Empty) = Empty
          go (Closure Epsilon) = Epsilon
          go (Closure k) = Closure (go k)
          go (Single k) = Single k
          go Epsilon = Epsilon
          go Empty = Empty