haskell – Parametrize by type constructor?

I made a tree structure (Tree) that represents an algebraic expression that contains two binary opperators the “question mark” Q/"?" and the “exclamation mark” E/"!".

Both are associative (that means a!(b!c)=(a!b)!c, and the same for the questionmark; this means the order of evaluation doesn’t matter and we can omit the parenthesis if we have a chain of the same operator), we do however have no precedence rules, that means we have to use parenthesis if we have a mix of operators: a?b!c would be invalid, it must be (a?b)!c or a?(b!c).

So now I wanted to make it a Show instance that prints out this expression in one line according to the rules outlined above. For that I wrote some helper functions surroundX that add parenthesis where needed.

So my question is: Is there a way to reduce the duplicated code, especially in the surroundX functions?

I thought that it would be nice to be able to pass E or Q as an additional parameter, but I didn’t find a way to make that work. But maybe there are other ways to simplify this.

data Tree = Unit | E Tree Tree | Q Tree Tree

surroundE a@(E _ _) = "(" ++ show a ++ ")"
surroundE x = show x
surroundQ a@(Q _ _) = "(" ++ show a ++ ")"
surroundQ x = show x

instance Show Tree where
 show Unit = "1"
 show (E a b) = surroundQ a ++ "!" ++ surroundQ b
 show (Q a b) = surroundE a ++ "?" ++ surroundE b

--example output
main = do
 print $ E (E Unit Unit) (E Unit (Q Unit Unit))
 print $ Q (E Unit Unit) (Q Unit (Q Unit Unit))

Try it online!