UNB/ CS/ David Bremner/ teaching/ cs4613/ lectures/ lecture6/ snippet-028.rkt
#lang plait
(define-type FLANG
  [Num  (val : Number)]
  [Add  (l : FLANG) (r : FLANG)]
  [Sub  (l : FLANG) (r : FLANG)]
  [Mul  (l : FLANG) (r : FLANG)]
  [Div  (l : FLANG) (r : FLANG)]
  [Id   (name : Symbol)]
  [Let1 (id : Symbol) (named-expr : FLANG) (bound-body : FLANG)]
  [Lam  (param : Symbol) (body : FLANG)]
  [Call (lam : FLANG) (val : FLANG)]) ; first type!

(define (arith-op op expr1 expr2)
  (let ([unwrap
         (λ (e) 
           (type-case FLANG e
             [(Num n) n]
             [else (error 'arith-op "NaN")]))])
    (Num (op (unwrap expr1)
             (unwrap expr2)))))