Composition of polymorphic functions

I think you can do:

g[x_] := With[{h = f[x]}, f[h] /; !MatchQ[h, _f]]

Then:

g /@ {2, {1, 2}, 3.5}

{65536, {1, 16}, g[3.5]}


Try the code

f[{a_, b_}] := {a^2, b^2};
f[c_Integer] := c^4;
g[x: _Integer | {a_, b_}] := f@f@x;
g /@ {2, {x, y}, 3.5} // InputForm

which returns the result

{65536, {x^4, y^4}, g[3.5]}

which is probably what you want.


Despite of what you say I would still recommend a "catch-all" that lets g inherit f's polymorphism effortlessly. For this it is crucial that g is defined with a delayed assignment:

f[{a_, b_}] = {a^2, b^2};
f[c_Integer] = c^4;
f[___] = Indeterminate;

g[x___] := f[f[x]]

You can replace Indeterminate with whatever you prefer, like $Failed or some form of Missing[].

Tests:

g /@ {2, {1, 2}, 3.5}

{65536, {1, 16}, Indeterminate}