From: Brian Hurt <bhurt@spnz.org>
To: "Tom Primožič" <tom.primozic@gmail.com>
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Type Inference and Overloading
Date: Mon, 10 Apr 2006 09:06:08 -0500 (CDT) [thread overview]
Message-ID: <Pine.LNX.4.63.0604100828560.9896@localhost.localdomain> (raw)
In-Reply-To: <c1490a380604100151s256d05y13cc8ffa11580770@mail.gmail.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed, Size: 3753 bytes --]
On Mon, 10 Apr 2006, Tom Primo¾iè wrote:
> Does anyone have any idea what kind of algorithm and structures would the
> compiler need to deploy to correctly infer the types for these functions:
>
> a : int -> float -> int
> a : float -> int -> int
I'm not sure there is one- in fact, I don't think there is. Consider if I
have the following case as above, and then I type:
let g = a;;
what's the type of g? Is it int -> float -> int or float -> int -> int?
What if I type:
let g x y = a y x;;
? What happens if I define two functions:
val c: int -> float -> int
val c: int -> int -> int
and then say:
let h x = c 3 x;;
What type does h have?
As a more general rule, how I deal with overloading in Ocaml is to use
modules and functors. Say I want to implement Newton's method. In other
languages, I'd depend upon overloading (possibly even operator
overloading). In Ocaml, I'd do something like:
module type Req =
type t (* the type of the number system *)
val sub : t -> t -> t (* subtraction *)
val div: t -> t -> t (* division *)
val within_epsilon: t -> t -> bool
end
module Newtons(Alg: Req) = struct
let meth f df x =
let rec loop x =
let x' = Alg.sub x (Alg.div (f x) (df x)) in
if (Alg.within_epsilon x x') then
x'
else
loop x'
in
loop x
end;;
Of course, a real implementation would be more complicated than this, but
this gets the idea across. I could then create "overloaded" versions of
my Newtons method just by calling the functor with the right modules, for
example:
module Float = struct
type t = float
let sub = ( -. );;
let div = ( /. );;
let within_epsilon x y = (abs_float (x -. y)) < 1e-14;;
end;;
module FloatNewtons = Newtons(Float);;
Similiar code bits can give me Newton's method for integers (use an
epsilon of 1), complexes, quaternions, even vectors/matricies.
Note that the performance overhead of using a functor is not signifigantly
larger than the performance overhead of using virtual or overloaded
functions- you're calling the sub, div, and within_epsilon functions via a
function pointer either way. And if you were to use ocamldefun, you could
eliminate even that cost.
Another advantage of Ocaml's funtors over overloaded functions/operators
is in documentation. You can see, right up front, in the .mli file, what
operations the algorithm needs. And the compiler checks to make sure you
are providing them.
The other important point to make here is that the operations provided to
a module are not implicitly "part of" the object itself. This is
especially important with comparison functions (such as within_epsilon
above)- I have come to the conclusion that comparison can *NOT* be a
member function:
http://enfranchisedmind.com/blog/archive/2006/01/30/62
http://enfranchisedmind.com/blog/archive/2006/03/28/123
As an example of this problem in action (and how functors solve it),
consider the above case except that sometimes I want to use a run-time
defined value for epsilon, instead of the hardcoded 1e-14. I could then
do:
module FloatE = struct
(* floating point with variable epsilon *)
type t = float
let sub = ( -. );;
let div = ( /. );;
let epsilon = ref 1e-14;;
let within_epsilon x y = (abs_float (x -. y)) < !epsilon;;
end;;
module FloatENewtons = Newtons(FloatE);;
Now I have two different Newton's methods on floats: one that uses the
fixed epsilon of 1e-14, and one that uses a variable epsilon. Note that
both FloatNewtons.meth and FloatENewtons.meth have the same type! If the
comparison method was built in, I'd need two different "types" of floats.
Brian
next prev parent reply other threads:[~2006-04-10 14:06 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-10 8:51 Tom Primožič
2006-04-10 11:57 ` [Caml-list] " skaller
2006-04-10 13:42 ` Andrej Bauer
2006-04-10 14:06 ` Brian Hurt [this message]
2006-04-10 14:43 ` Tom Primožič
2006-04-11 16:11 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.63.0604100828560.9896@localhost.localdomain \
--to=bhurt@spnz.org \
--cc=caml-list@yquem.inria.fr \
--cc=tom.primozic@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox