English 中文(简体)
How can I simplify this ocaml pattern-matching code?
原标题:

I m writing a simple little ocaml program that reads an algebraic statement in from a file, parses it into an AST using ocamllex/ocamlyacc, reduces it, and then prints it. The part where I m reducing the expression seems a bit... ugly. Is there any way I can simplify it?

(* ocaml doesn t seem to be able to take arithmetic operators
 as functions, so define these wrappers for them *)
let add x y =
  x + y

let sub x y =
  x - y

let mul x y =
  x * y

let div x y =
  x / y

(* Are term1 and term2 both ints? *)
let both_ints term1 term2 =
  match (term1, term2) with
    | (Term (Number x), Term (Number y)) -> true
    | (_, _) -> false

(* We know that both terms are reducable to numbers, so combine
  them *)
let combine_terms func x y =
  match (x, y) with
      (Term (Number t1), Term (Number t2)) ->
        (Term (Number (func  t1  t2)))
    | (_, _) -> raise InvalidArg

(* Reduce the expression as much as possible *)
let rec reduce_expr expr =
  match expr with
      Plus (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms add reduced_x reduced_y)
      else
        Plus (reduced_x, reduced_y)
    | Minus (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms sub reduced_x reduced_y)
      else
        Minus (reduced_x, reduced_y)
    | Multiply (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms mul reduced_x reduced_y)
      else
        Multiply (reduced_x, reduced_y)
    | Divide (x, y) ->
        let reduced_x = reduce_expr x
        and reduced_y = reduce_expr y in
      if both_ints reduced_x reduced_y then
        (combine_terms div reduced_x reduced_y)
      else
        Divide (reduced_x, reduced_y)
    | Term x -> Term x
最佳回答

You can remove the both_ints, and combine_terms functions as well as some if statements, by matching the type containing Number within the operation functions, such as:

let div x y = match x,y with
    | Number x, Number y -> Number (x / y)
    | _ -> Divide (x,y)

...
let rec reduce_expr expr = match expr with
    ...
    | Divide (x,y) -> div (reduce_expr x) (reduce_expr y)
    ...
问题回答

暂无回答




相关问题
ocamlc, module compilation

I wrote an app in ocaml. It consist of several modules: Util (util.ml) Work1 (work1.ml) -- open Util Work2 (work2.ml) -- open Util, too Main (main.ml) -- open all of them. When i compile its, using ...

How can I simplify this ocaml pattern-matching code?

I m writing a simple little ocaml program that reads an algebraic statement in from a file, parses it into an AST using ocamllex/ocamlyacc, reduces it, and then prints it. The part where I m reducing ...

How can I create a type with multiple parameters in OCaml?

I m trying to create a type that has multiple type parameters. I know how to make a type with one parameter: type a foo = a * int But I need to have two parameters, so that I can parameterize the ...

Hashtable indexed on several fields

I m currently programming an OCaml module defining a type corresponding to a CPU register. The interface of this module is the following : (* * Defines a type which represents a R3000 register. *) ...

Extending an existing type in OCaml

I ve been doing some OCaml programming lately to learn the language and to get more acquainted with functional programming. Recently, I ve started to think that I d like to be able to extend an ...

Ocaml Syntax Error

What s wrong with this code? I can t figure it out: let parent (rules : grammar) (symbol1 : string) (symbol2 : string) : (SymbolSet.t) = try SymbolSet.singleton (getParent [symbol1; symbol2] ...

热门标签