From: Brian Rogoff <bpr@artisan.com>
To: Diego-Olivier.FERNANDEZ-PONS@cicrp.jussieu.fr
Cc: caml-list@inria.fr
Subject: Polymorphic recursion 9Was Re: [Caml-list] Doubly-linked list)
Date: Mon, 19 Aug 2002 08:58:29 -0700 [thread overview]
Message-ID: <15713.5541.413031.271962@granite.artisan.com> (raw)
In-Reply-To: <Pine.A32.3.95.1020819121715.76782C-100000@ibm1.cicrp.jussieu.fr>
Diego Olivier Fernandez Pons writes:
> Brian Rogoff a écrit :
> > With OCaml 3.05 and above, you'll be able to use polymorphic methods to
> > get non-uniform recursion. This issue has come up a lot on the list
> > (see the archives) over the years and several proposals were made for
> > adding this capability to the language. I don't know if adding this
> > feature is a priority for the developers; it isn't clear that the data
> > structures in Okasaki's book constitute a strong enough argument for
> > adding it.
>
> Non-uniform recursion allows you to capture structure invariants in
> your type, which means that the correction of the algorithms will not
> be proved by the programmer but by the type-checker.
Oh I'm not arguing that point, I totally agree that it's omission is a
bad thing. However, not everyone agrees, since you it becomes a lot tougher
to build a monomorphizing compiler if you allow it, though it has been
suggested that the same tricks you use to manually remove polymorphic
recursion could be used in an SSC (sufficiently smart compiler).
Anyways, since OCaml 3.05 allows first class polymorphism on records, you
don't even need to use "polymorphic recots" to get non-uniform recursion;
simply mapping the OOP to records does the trick. Here's the first example
from OKasaki which uses polymorphic recursion, done in OCaml with this
direct approach
module type RANDOM_ACCESS_LIST =
sig
type 'a ra_list
val empty : 'a ra_list
val is_empty : 'a ra_list -> bool
val cons : 'a -> 'a ra_list -> 'a ra_list
val head : 'a ra_list -> 'a
val tail : 'a ra_list -> 'a ra_list
val lookup : int -> 'a ra_list -> 'a
val update : int -> 'a -> 'a ra_list -> 'a ra_list
end
module AltBinaryRandomAccessList : RANDOM_ACCESS_LIST =
(* assumes polymorphic recursion! *)
struct
type 'a ra_list = Nil
| Zero of ('a * 'a) ra_list
| One of 'a * ('a * 'a) ra_list
let empty = Nil
let is_empty = function Nil -> true | _ -> false
(* Use first class polymorphism to get the effect of explicitly typing
the polymorphic recursion
*)
type dictionary =
{ cons : 'a. dictionary -> 'a -> 'a ra_list -> 'a ra_list;
uncons : 'a. dictionary -> 'a ra_list -> 'a * 'a ra_list;
lookup : 'a. dictionary -> int -> 'a ra_list -> 'a;
fupdate : 'a. dictionary -> ('a -> 'a) -> int -> 'a ra_list -> 'a
ra_list
}
(* Define the methods, taking care that the recursive calls go through
the dictionary
*)
let cons' dict x l =
match l with
Nil -> One (x, Nil)
| Zero ps -> One (x, ps)
| One (y,b) -> Zero (dict.cons dict (x, y) b)
let uncons' dict l =
match l with
Nil -> raise Not_found
| One (x,Nil) -> (x,Nil)
| One (x,ps) -> (x, Zero ps)
| Zero ps ->
let ((x,y),ps') = dict.uncons dict ps in
(x, One (y, ps'))
let lookup' dict i l =
match i,l with
(i, Nil) -> raise Not_found
| (0, One (x, ps)) -> x
| (i, One (x, ps)) -> dict.lookup dict (pred i) (Zero ps)
| (i, Zero ps) ->
let (x, y) = dict.lookup dict (i / 2) ps
in if i mod 2 = 0 then x else y
let rec fupdate' dict f i l =
match i,l with
(i, Nil) -> raise Not_found
| (0, One (x, ps)) -> One (f x, ps)
| (i, One (x, ps)) -> dict.cons dict x (dict.fupdate dict f (i-1) (Zero
ps))
| (i, Zero ps) ->
let f' (x, y) = if i mod 2 = 0 then (f x, y) else (x, f y) in
Zero (dict.fupdate dict f' (i / 2) ps)
(* Make the sole dictionary which will be called *)
let methods =
{ cons = cons'; uncons = uncons'; lookup = lookup'; fupdate = fupdate' }
(* Make the actual functions *)
let cons x l = cons' methods x l
let uncons l = uncons' methods l
let head xs = let (x, _) = uncons xs in x
let tail xs = let (_, xs') = uncons xs in xs'
let lookup i xs = lookup' methods i xs
let update i y xs = fupdate' methods (fun x -> y) i xs
end
> I think it is a big improvment. Chris Okasaki's data structure may not
> be a strong enough argument, but more complicated data structures are
> being studied.
I agree, and I hope that in the future we won't have to use hacks like the
above to get polymorphic recursion, but that it will be supported more
directly. The style above, besides being indirect, is also a little uglier
still when you're using the tail recursive accumulator passing style
because your recursive functions have funny names and signatures. In any
case, this kind of hack will allow you to translate these structures and
won't require much rework when polymorphic recursion is finally added
"for real"
-- Brian
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
next prev parent reply other threads:[~2002-08-19 15:58 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-08-13 8:00 [Caml-list] Doubly-linked list Oleg
2002-08-13 8:54 ` Markus Mottl
2002-08-13 15:52 ` Oleg
2002-08-13 11:00 ` Diego Olivier Fernandez Pons
2002-08-13 14:30 ` Oleg
2002-08-13 15:11 ` Anton Moscal
2002-08-13 16:12 ` Oleg
2002-08-13 17:16 ` Max Kirillov
2002-08-14 0:49 ` Max Kirillov
2002-08-13 18:23 ` Anton E. Moscal
2002-08-13 16:16 ` Brian Rogoff
2002-08-14 8:13 ` Diego Olivier Fernandez Pons
2002-08-14 15:43 ` Brian Rogoff
2002-08-19 10:38 ` Diego Olivier Fernandez Pons
2002-08-19 15:58 ` Brian Rogoff [this message]
2002-08-21 8:04 ` Polymorphic recursion 9Was Re: [Caml-list] Doubly-linked list) Diego Olivier Fernandez Pons
2002-08-21 15:48 ` Brian Rogoff
2002-08-23 8:14 ` Diego Olivier Fernandez Pons
2002-08-23 21:57 ` John Max Skaller
2002-08-27 13:00 ` Diego Olivier Fernandez Pons
2002-08-28 14:50 ` John Max Skaller
2002-08-28 17:27 ` [Caml-list] FELIX (was: Polymorphic recursion) Oleg
2002-08-19 23:17 ` [Caml-list] Doubly-linked list james woodyatt
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=15713.5541.413031.271962@granite.artisan.com \
--to=bpr@artisan.com \
--cc=Diego-Olivier.FERNANDEZ-PONS@cicrp.jussieu.fr \
--cc=caml-list@inria.fr \
/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