# R. G.
- Type des expressions arithmétiques (`+, -, /, *`)
- Fonction pour les évaluer
```ocaml=
type bin_op =
| Add
| Sub
| Mul
| Div
type 'a expr =
| Bin_op of bin_op * expr * expr
| Value of 'a
| Var of string
let rec eval var_tbl bin_op_f = function
| Value n -> Ok n
| Var var ->
begin match Hashtbl.find_opt var_tbl var with
| Some n -> Ok n
| None -> Error (Printf.sprintf "Variable %s not defined" var)
end
| Bin_op (bin_op, e1, e2) ->
let op = bin_op_f bin_op in
match eval e1 with
| Error _ as err -> err
| Ok res1 ->
match eval e2 with
| Error _ as err -> err
| Ok res2 ->
match op res1 res2 with
| exception Divide_by_zero -> Error "Div zero"
| res -> Ok res
let rec eval var_tbl bin_op_f = function
| Value n -> Value n
| Var var ->
begin match Hashtbl.find_opt var_tbl var with
| Some n -> Value n
| None -> Var var
end
| Bin_op (Mul, e1, e2) ->
begin match e1, e2 with
| Value n1, Value n2 ->
Value (n1 * n2)
| Var _ as var, Value _ as value
| Value _ as value, Var _ as var ->
Bin_op (value, var)
| Value _ as value, Bin_op (Add, e1, e2)
| Bin_op (Add, e1, e2), Value _ as value ->
let e1 = Bin_op (Mul, value, e1) in
let e2 = Bin_op (Mul, value, e2) in
eval (Bin_op (Add, e1, e2))
end
| Bin_op (bin_op, e1, e2) ->
let op = bin_op_f bin_op in
match eval e1 with
| Ok res1 ->
match eval e2 with
| Error _ as err -> err
| Ok res2 ->
match op res1 res2 with
| exception Divide_by_zero -> Error "Div zero"
| res -> Ok res
(*
n/p => pgcd
6x*x / 2 x = 3x
x/(1 + x)
t + t + t + t
t ~ m * m * m * m
3x + ... + 4x = 7x
(3x(y+1))/z
*)
(*
SUM (n * v^k)
(string, int * int) Hashtbl.t
(expr, int) Hashtbl.t
((expr, int) Hashtbl.t, int) Hashtbl.t
(int * (string * int) list) list
3x² + 6x² = 9x²
3x² - 3x²
0x²
Sum (n_i * Mul (x_j ^ n_j))
(x, 3, 2) (x, 2, 1) (y, 3, 1) (_, 1, 0)
3x² + 2x + 3y + 1
*)
(* 4(x + y) = 4x + 4y *)
(* (x + 3) + 4 *)
(* val pgcd: int -> int -> int *)
type rat = R of int * int
let simplify_rat (R (p, q)) =
let pgcd = pgcd p q in
R (p / pgcd, q / pgcd)
let bin_op = function
| Add ->
fun (R (p1, q1)) (R (p2, q2)) ->
let p1 = p1 * q2 in
let q1 = q1 * q2 in
let p2 = p2 * q1 in
R (p1 + p2, q1)
| Sub -> ...
| Mul ->
fun (R (p1, q1)) (R (p2, q2)) ->
R (p1 * p2, q1 * q2)
let bin_op rat = simplify_rat (bin_op rat)
```