caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jon Harrop <jon@ffconsultancy.com>
To: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] How important are circular lists/recursive objects?
Date: Thu, 5 Apr 2007 01:51:18 +0100	[thread overview]
Message-ID: <200704050151.19005.jon@ffconsultancy.com> (raw)
In-Reply-To: <Pine.LNX.4.64.0704041848540.5725@localhost>

On Thursday 05 April 2007 00:28, Brian Hurt wrote:
> On Tue, 3 Apr 2007, Andrej Bauer wrote:
> > Brian Hurt wrote:
> >> Does anyone  actually use this construct, and if so, for what?
> >
> > When I teach my students "theory" of programming languages, we write
> > interpreters for mini languages. The recursive data structures are used
> > to create closures of recursive functions, environments that contain
> > mutually recursive values, closures of objects, etc. Life would be very
> > hard without this feature.
>
> No.  I'm just thinking about circular lists.

The cyclic graph in an interpreter is a closure<->environment cycle, whereas a 
cyclic list involves only one structure (the list itself). However, I think 
the problems and properties are equivalent in this context.

> It's somewhat off-topic, but here's where I'm comming from.  Imagine a
> language with variant types and Wadler-style views
>
> For those who don't know what Wadler style views, the long intro is:
> http://citeseer.ist.psu.edu/wadler86views.html

How is Wadler's proposal related to views (active patterns) in F#?

> The short intro is that it's a way to tie new data structures into pattern
> matching.  You could define a new data type, and a new operator on that
> datatype, for example (in pseudo-Ocaml):
>  	type 'a t = Cons of 'a * 'a t | Nil;;
>
>  	let cons h t = Cons(h, t);;
>
>  	let decons arg matches doesnt_match =
>  		match arg with
>
>  			| Cons(h, t) -> matches h t
>  			| Nil -> doesnt_match ()
>
>  	;;
>
> You could then tie the cons and decons functions in with the argument,
> maybe like:
>
>  	define ( ::. ) = cons, decons ;;
>
> so that when the compiler saw the code:
>
>  	match lst with
>
>  		| h ::. t -> expr1
>  		| _ -> expr2
>
> it would compile it as:
>  	decons lst (fun h t -> expr1) (fun () -> expr2)
>
> Allowing users of your new data structure to pattern match on the data
> structure using the normal operators for that data structure.

You can do similar things with F#. A simpler example is getting rid of the 
integer total orderings of OCaml in favour of a more sane sum type:

  let (|Less|Equal|Greater|) c =
    if c<0 then Less else
      if c=0 then Equal else Greater

> As you might guess from the above example, at this point you don't need to
> define lists as a built-in data structure.

Is that not already true because pattern matching over variant type 
constructors provides everything you need?

> You have all the capabilities 
> you need to implement lists as a library.  With one, minor, exception- how
> does the compiler handler expressions like:
>  	let rec a = 1 ::. 2 ::. a in ...
>
> As that code compiles like:
>  	let rec a = cons 1 (cons 2 a) in ...

Provided it compiles to:

  let rec a = Cons(1, Cons(2, a))

you're ok.

> Ocaml handles this construct because it knows about lists.  But it doesn't
> know about this t data structure.

OCaml can already do that with user-defined data structures.

> It could be defined in another module, 
> and be an abstract type.  It could have an arbitrarily complicated
> definition.  There is no garuentee in this case that cons doesn't look at
> the argument.  In fact, it'd be perfectly reasonble for t to be an
> implementation of Okasaki's random access lists:
> http://citeseer.ist.psu.edu/okasaki95purely.html
> at which point the implementation of cons *would* inspect the tail
> argument.

Yes.

> So, the question is: if a (at this point in time entirely hypothetical)
> programming language decided to go this route, and decided to simply
> outlaw self-referential data structures such as circular lists, would this
> be a problem?

Can you define more precisely what you mean by "self-referential data 
structures" because that either seems to cover arbitrarily little or too many 
useful data structures.

But I think these are orthogonal concepts. OCaml already forbids:

  let rec a = cons 1 (cons 2 a)

because you can only use constructors in that context.

> Not that recursive and mutually recursive functions would 
> still allowed, those are downright necessary.  I'm only thinking
> self-referential data structures.

But data structures can contain closures and closures contain environments 
than can refer back to the data structure.

> But the compiler needs to know the 
> structure of a closure, for obvious reasons, so the compiler knowing how
> to cheat and "fill in" the closure with the right values after those
> values have been generated isn't a problem.  I've become quite fond of the
> continuation passing style of code recently.
>
> And this probably holds for a lazy thunk as well, especially considering a
> lazy thunk contains a closure (at least initially).
>
> I will note that in Ocaml you can do:
> # let rec x = lazy (Lazy.force x);;
> val x : 'a Lazy.t = <lazy>
> # Lazy.force x;;
> Exception: Lazy.Undefined.
> #
>
> Simply because it compiles doesn't mean it makes sense, necessarily.

I have a patch for the compiler that ensures sensicalness of programs. ;-)

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
OCaml for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists


  reply	other threads:[~2007-04-05  0:56 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-02 23:55 Brian Hurt
2007-04-03  6:24 ` Gleb Alexeyev
2007-04-03  6:58 ` [Caml-list] " Ville-Pertti Keinonen
2007-04-03  7:00 ` Andrej Bauer
2007-04-03 12:09   ` Jon Harrop
2007-04-03 13:31     ` Bruno De Fraine
2007-04-04 23:28   ` Brian Hurt
2007-04-05  0:51     ` Jon Harrop [this message]
2007-04-03 12:49 ` Philippe Wang
2007-04-04  3:52 ` Stefan Monnier
2007-04-04  5:28   ` [Caml-list] " skaller
2007-10-04 17:48     ` Fabrice Marchant
2007-10-04 20:39       ` skaller
2007-10-04 21:36         ` rossberg
2007-10-04 22:25           ` skaller
2007-10-05 10:42             ` Dominique Martinet
2007-10-08  9:57             ` Andreas Rossberg
2007-04-04  8:45   ` Don Syme

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=200704050151.19005.jon@ffconsultancy.com \
    --to=jon@ffconsultancy.com \
    --cc=caml-list@yquem.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;
as well as URLs for NNTP newsgroup(s).