An Algebraic View of Program Composition