---
# System prepended metadata

title: R. G.

---

# 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)
```
