I was wondering how could I achieve the following:
- have all the "business logic" in a file
- have a main.ml that uses that business logic
Business logic:
type point = {x:float; y:float;}
let pi_known = 3.141592653589793238462643383279502884197169399375105820974944592307816406286
let percentage_error pi_estimated =
((pi_known -. pi_estimated) /. pi_known) *. 100.0
let pi_and_error pi error =
Printf.sprintf "Pi's value :: %.10f Error rate :: %.10f %.%" pi error
let point_to_string { x = x; y = y } =
Printf.sprintf "%.2f %.2f" x y
let gen_point xr yr =
{x=xr; y=yr}
let distance_between_points p q =
(p.x -. q.x) *. (p.x -. q.x) +. (p.y -. q.y) *. (p.y -. q.y)
let distance_from_origin c =
distance_between_points c (gen_point 0.0 0.0)
let count_within ~counter:n =
let rec count_within_aux ~counter:n ~within:m =
match n, m with
| 0, m -> m
| n, m ->
let cc = gen_point (Random.float 1.0) (Random.float 1.0) in
let dist = distance_from_origin cc in
match dist with
| dist when dist <= 1.0 -> count_within_aux ~counter:(n - 1) ~within:(m + 1)
| dist when dist > 1.0 -> count_within_aux ~counter:(n - 1) ~within:m
| _ -> 0 in
count_within_aux ~counter:n ~within:0
let count_within_stepping ~counter:n ~stepping:s =
let rec count_within_stepping_aux ~counter:n ~within:m ~acc:acc =
match n, m, acc with
| n, m, acc when n <= 0 -> m
| n, m, acc ->
let c = count_within s in
let pi = ((float_of_int m) /. (float_of_int acc)) *. 4.0 in
let r = percentage_error pi in
print_endline (pi_and_error pi r);
count_within_stepping_aux ~counter:(n-s) ~within:(m+c) ~acc:(acc+s) in
count_within_stepping_aux ~counter:n ~within:0 ~acc:0
pi.mli:
(*
* Point in a two-dimensional Euclidean space
*)
type point = {x:float; y:float;}
val point_to_string : point -> string
val gen_point : float -> float -> point
(*
* 'Euclidean distance or Euclidean metric is the "ordinary" straight-line distance between
* two points in Euclidean space. With this distance, Euclidean space becomes a metric space.
* The associated norm is called the Euclidean norm.
* Older literature refers to the metric as Pythagorean metric.'
* https://en.wikipedia.org/wiki/Euclidean_distance
*)
val distance_between_points : point -> point -> float
val distance_from_origin : point -> float
val count_within : counter:int -> int
val count_within_stepping : counter:int -> stepping:int -> int
val percentage_error : float -> float
val pi_and_error : float -> float -> string
main.ml:
let main () =
Random.self_init();
let num_iter = Sys.argv.(1) in
let n = int_of_string num_iter in
print_endline ("Number of iterations :: " ^ num_iter);
let pi_estimated = ((float_of_int (Pi.count_within_stepping n (n / 20))) /. (float_of_int n)) *. 4.0 in
let r = Pi.percentage_error pi_estimated in
print_endline (Pi.pi_and_error pi_estimated r)
let () =
main ()
_oasis:
Name: Pi
Version: 0.1
Synopsis: Nope
Authors:
Istvan <[email protected]>
License: MIT
Homepage: http://0.0.0.0
OASISFormat: 0.4
BuildTools: ocamlbuild
Plugins: META (0.4), DevFiles (0.4)
Executable "pi"
Path: src
MainIs: main.ml
CompiledObject: best
BuildDepends:
str,unix
Unfortunatelly when I compile this and run it it returns nothing while if I merge main.ml and pi.ml it works as expected. What am I missing?
UPDTE:
After adding the mli file to the project and changing main.ml as it was suggested by @gallais it works as expected.
It turns out that mli files are necessary for using modules. Having src/x.ml and src/x.mli is required. If these files are present X can be referenced from main.ml.