Search code examples
functional-programmingpattern-matchingocaml

How to refactor this pattern matched OCaml piece of code


I'm learning OCaml from the MOOC offered by Université Paris Diderot. At the moment i have not encounter major struggle with functional thinking, but i do find this piece of code, a little bit ugly. How can i refactor it, so i can write general evaluation of e1, and e2 that serves for two latest branches of the match statement included in the simplify function. The idea of this function is to transform e * 0 or 0 * e into 0; e * 1 or 1 * e into e; and e + 0 or 0 + e into e.

type exp =
  | EInt of int
  | EAdd of exp * exp
  | EMul of exp * exp;;

let eval expression = 
  let rec aux = function
    | EInt x        -> x
    | EAdd (e1, e2) -> (aux e1) + (aux e2)
    | EMul (e1, e2) -> (aux e1) * (aux e2)
  in aux expression;;

let simplify expression = 
  match expression with
  | EInt _        -> expression
  | EAdd (e1, e2) -> 
      let v1 = eval e1 in
      let v2 = eval e2 in
      if v1 = 0 then e2
      else if v2 = 0 then e1
      else expression 
  | EMul (e1, e2) ->
      let v1 = eval e1 in
      let v2 = eval e2 in
      if v1 = 0 || v2 = 0 then EInt 0
      else if v1 = 1 then e2
      else if v2 = 1 then e1 
      else expression;;

I appreciate you help! Thanks!


Solution

  • I guess you can have a function like this:

    let simplifyop identity zero exp e1 e2 =
        let v1 = eval e1 in
        let v2 = eval e2 in
        if v1 = identity then e2
        else if v2 = identity then e1
        else
            match zero with
            | None -> exp
            | Some z ->
                if v1 = z || v2 = z then EInt z
                else exp
    

    Then your cases look like this:

    | EAdd (e1, e2) -> simplifyop 0 None expression e1 e2
    | EMul (e1, e2) -> simplifyop 1 (Some 0) expression e1 e2