#lang plait (define-type BinOp [plus] [++]) ;; string concat (define-type Exp [binE (operator : BinOp) (left : Exp) (right : Exp)] [numE (value : Number)] [strE (value : String)]) (define-type Value [strV (value : String)] [numV (value : Number)]) (define (on-strings func l r) (cond [(and (strV? l) (strV? r)) (strV (func (strV-value l) (strV-value r)))] [else (error 'interp "expected 2 numbers")])) (define (on-nums func l r) (cond [(and (numV? l) (numV? r)) (numV (func (numV-value l) (numV-value r)))] [else (error 'interp "expected 2 numbers")])) (define (interp expr) (type-case Exp expr [(numE n) (numV n)] [(strE s) (strV s)] [(binE o l r) (let ([l-val (interp l)] [r-val (interp r)]) (type-case BinOp o [(++) (on-strings string-append l-val r-val)] [(plus) (on-nums + l-val r-val)]))])) (test (interp (binE (plus) (numE 3) (numE 4))) (numV 7)) (test (interp (binE (++) (strE "3") (strE "4"))) (strV "34")) (test/exn (interp (binE (plus) (numE 3) (strE "4"))) "numbers")