def distribute(A, B):
 def distribute_rl(expr):
  for (i, arg) in enumerate(expr.args):
   if isinstance(arg, B):
    (first, b, tail) = (expr.args[:i], expr.args[i], expr.args[(i + 1):])
    return B(*[A(*((first + (arg,)) + tail)) for arg in b.args])
  return expr
 return distribute_rl

def distribute ( A , B ) : def distribute_rl ( expr ) : for ( i , arg ) in enumerate ( expr . args ) : if isinstance ( arg , B ) : ( first , b , tail ) = ( expr . args [ : i ] , expr . args [ i ] , expr . args [ ( i + 1 ) : ] ) return B ( * [ A ( * ( ( first + ( arg , ) ) + tail ) ) for arg in b . args ] ) return expr return distribute_rl
turns an a containing bs into a b of as where a .