Add Max/Min/First/Last using semigroups