"""Draw a typing derivation for (lambda x. x + 1) 3. Tested with Python 3.14.4, NumPy 2.3.5 and Matplotlib 3.10.7. Run from _media; the matching opaque white PNG is written to the CWD. This is a diagram of stated typing rules, not a compiler implementation. """ from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from matplotlib.patches import FancyArrowPatch, FancyBboxPatch def main(): plt.rcParams.update({"font.family": "DejaVu Sans", "font.size": 13}) fig, ax = plt.subplots(figsize=(10.5, 7.0), dpi=100) fig.patch.set_facecolor("white") ax.set(xlim=(0, 12), ylim=(0, 8)) ax.axis("off") ink, blue, green = "#203040", "#155d8a", "#187355" def box(x, y, width, label, color=blue): ax.add_patch(FancyBboxPatch( (x - width / 2, y - 0.34), width, 0.68, boxstyle="round,pad=0.08", facecolor="#f3f7fb", edgecolor=color, linewidth=1.6, )) ax.text(x, y, label, ha="center", va="center", color=color) def arrow(start, end): ax.add_patch(FancyArrowPatch( start, end, arrowstyle="-|>", mutation_scale=17, linewidth=1.6, color=blue, )) ax.text(6, 7.62, "Checking a function call from its parts", ha="center", va="center", fontsize=20, weight="bold", color=ink) ax.text(6, 7.10, "Read downward: check operands, sum, function, argument and call result.", ha="center", va="center", fontsize=12, color=ink) box(2.2, 6.18, 3.4, "x : int ⊢ x : int") box(6.2, 6.18, 3.4, "x : int ⊢ 1 : int") arrow((2.2, 5.75), (3.5, 4.99)) arrow((6.2, 5.75), (4.9, 4.99)) ax.text(4.2, 5.40, "addition rule", ha="center", fontsize=11, color=ink) box(4.2, 4.55, 5.6, "x : int ⊢ x + 1 : int") arrow((4.2, 4.12), (4.2, 3.16)) ax.text(4.48, 3.65, "abstraction: bind x", ha="left", fontsize=11, color=ink) box(4.2, 2.72, 6.4, "∅ ⊢ λx. x + 1 : int → int") box(9.5, 2.72, 2.8, "∅ ⊢ 3 : int", green) arrow((4.2, 2.29), (5.3, 1.50)) arrow((9.5, 2.29), (6.7, 1.50)) ax.text(6.5, 1.99, "application: argument type matches int", ha="center", fontsize=11, color=ink, bbox={"facecolor": "white", "edgecolor": "none", "pad": 2}) box(6, 1.08, 9.6, "∅ ⊢ (λx. x + 1) 3 : int", green) ax.text(6, 0.35, "∅ = no free-name assumptions. Arrows connect premises to conclusions.", ha="center", va="center", fontsize=11, color=ink) fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01) fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), facecolor="white", transparent=False) plt.close(fig) if __name__ == "__main__": main()