Causal Reasoning for Algorithmic Fairness