// Model expressions -- heterogeneous, recursive data structures type Expression = | Variable of string | Number of int | Negation of Expression | Sum of Expression * Expression | Difference of Expression * Expression | Product of Expression * Expression | Power of Expression * int | Quotient of Expression * Expression | Function of name:string * latex:(string->string) * arg:Expression //syntactic sugar, but makes a big difference if doing a lot of mathematical work static member (+) (e1,e2) = Sum(e1,e2) static member (*) (e1,e2) = Product(e1,e2) static member (-) (e1,e2) = Difference(e1,e2) static member (/) (e1,e2) = Quotient(e1,e2) static member (~-) (e) = Negation e static member Pow (exp:Expression,i:int) = Power(exp,i) let sqrt(e) = Function("sqrt",sprintf @"\sqrt{%s}",e) let inline (~&) (i:int) = Number(i) let rec latex (exp:Expression) = let paren s = sprintf @"\left( %s \right)" s match exp with | Variable s -> sprintf " %s " s | Number i -> sprintf " %d " i | Negation e -> (match e with | Sum _ | Difference _ | Negation _ -> paren (latex e) | _ -> latex e) |> sprintf @" - %s" | Sum(e1,e2) -> sprintf @"%s + %s" (latex e1) (latex e2) | Difference(e1,e2) -> (match e2 with | Sum _ | Difference _ | Negation _ -> paren (latex e2) | _ -> latex e2) |> sprintf @"%s - %s" (latex e1) | Product(e1,e2) -> let term1 = match e1 with | Sum _ | Difference _ -> paren (latex e1) | _ -> latex e1 let term2 = match e2 with | Sum _ | Difference _ | Negation _-> paren (latex e2) | _ -> latex e2 sprintf @"%s \cdot %s" term1 term2 | Power(e,p) -> (match e with | Number _ | Variable _ -> latex e | _ -> paren (latex e)) |> fun s -> sprintf @" %s ^{ %d }" s p | Quotient (num,denom) -> sprintf @"\frac{%s}{%s}" (latex num) (latex denom) | Function (_,fnTex,exp) -> fnTex(latex exp) let a,b,c = Variable "a", Variable "b", Variable "c" (-b + sqrt(b**2 - &4*a*c)) / (&2 * a) |> latex