# Composition of polymorphic functions

Using pattern matching one can easily create polymorphic functions in Mathematica

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


Now I want to create another function which is also polymorphic and calls the previous function, the simplest version of what I want to achieve is:

g[{a_, b_}] := f[f[{a, b}]];
g[c_Integer] := f[f[c]];


Note that the last two lines are "basically the same". What is the best way to avoid this redundancy? One possible solution I found is

Module[{a, b, c},
Scan[Apply[(g[#1] := f[f[#2]]) &],{{{a_, b_}, {a, b}},{c_Integer, c}}]]


Other suggestions? Note that the "catch all" g[d_]:=f[f[d]] is "not allowed", as it will give different results for example when g[3.5] is called.

Edit: In this case the following is also possible

g[x_]:=f[f[x]] /; IntegerQ[x] || (Length[x] == 2)


That might be a bit cumbersome for more complicated patterns however.

Edit 2: Also possible, same critique as above

g[x_Integer|x_List? (Length[#]==2&)]:=f[f[x]]


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.

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]}

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}