caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: brogoff@speakeasy.net
To: Nicolas Cannasse <warplayer@free.fr>
Cc: Pierre Weis <pierre.weis@inria.fr>,
	Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>,
	"caml-list@inria.fr" <caml-list@inria.fr>
Subject: Re: [Caml-list] Python's yield, Lisp's call-cc or C's setjmp/longjmp in OCaml
Date: Thu, 18 Dec 2003 10:44:17 -0800 (PST)	[thread overview]
Message-ID: <Pine.LNX.4.44.0312181008040.32105-100000@grace.speakeasy.net> (raw)
In-Reply-To: <004c01c3c504$62407b80$0274a8c0@PWARP>

On Thu, 18 Dec 2003, Nicolas Cannasse wrote:
> > [...]
> > > This only works for simple examples. Try for example writing a
> > > function which successively yields all possible moves for a chess
> > > board. The "yield" operator really helps there.
> >
> > Very interesting: please give us the code corresponding to this
> > example, in order for us to realize how the full power of the "yield"
> > operator helps to solve this problem.
> >
> > Pierre Weis
> >
>
> One simple sample is tree walking :
> "if there was yield in ocaml"
>
> type 'a tree =
>     |  Node of 'a tree list
>     |  Leaf of 'a
>
> let rec iterator = function
>     | Node l -> List.iter iterator l
>     | Leaf x -> yield x

I think this problem is relatively easily handled by the simple home made
lazy lists I described before, available even in SML or Lisp.

The canonical problem of this class is the "same fringe" problem for trees,
where you'd like to compare the tree fringe but not have to build the entire
fringe and do all of the comparisons, but just walk the tree and bail after the
first inequality. I've appended the code of a simple polymorphic generator
module, and two different tree representations to test samefringe on. I believe
that the code is not much longer than the equivalent Sather code, if we take for
granted that the generator code is part of the library.

If this kind of stuff interests you, I suggest you also check out "zippers", and
the paper called "That About Wraps It Up" on using Y in ML programming. The
first, because the notion of "whole + context" is a useful one for traversing
and manipulating data structures in a functional style, the second because you
would like to know about simulating coroutines with first class functions.

Of course, OCaml also has support for laziness with both Lazy (an lazy) as well
as streams which offer other approaches, but I think the simple stuff buys you a
lot of what iterators do.

-- Brian

module Generator =
  struct
     type  'a t = Nil | Cons of 'a * (unit -> 'a t)

     (* Equality of two generators *)

     let rec eq lz1 lz2 =
       match (lz1,lz2) with
         Nil, Nil -> true
       | Cons (v1,f1), Cons (v2,f2) -> (v1 = v2) && eq (f1()) (f2())
       | _ -> false

     exception Empty

     let make_nil () = Nil

     let make x = Cons (x, make_nil)

    (* Combines two generators *)

     let rec concat f g =
       match f () with
         Nil -> g ()
       | Cons(x,h) -> Cons(x, fun () -> concat h g)

    (* Return the first item of the generator paired with the rest *)

     let yield : 'a t -> 'a * 'a t = function
         Nil -> raise Empty
       | Cons(x,h) -> x, (h ())
  end;;

module Tree =
  struct

    (* A generic binary tree data type
    *)
    type 'a t = Leaf of 'a | Node of 'a t list

    let make_leaf x = Leaf x
    let make l = Node l

    let rec fringe = function
        Leaf(x) -> Generator.make x
      | Node[] -> Generator.Nil
      | Node(x::xs) ->
          Generator.concat (fun () -> fringe x) (fun () -> fringe (Node xs))

    let samefringe t1 t2 = Generator.eq (fringe t1) (fringe t2)
  end;;

module BinaryTree =
  struct

    (* A generic binary tree data type
    *)
    type 'a t = Leaf of 'a | Node of 'a t * 'a t

    let make_leaf x = Leaf x
    let make l r = Node(l,r)

    let rec fringe = function
        (Leaf x) -> Generator.make x
      | (Node(l,r)) ->
          Generator.concat (fun () -> fringe l) (fun () -> fringe r);;

    let samefringe t1 t2 = Generator.eq (fringe t1) (fringe t2)
  end;;


-------------------
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


  parent reply	other threads:[~2003-12-18 18:44 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-12-16 13:13 Nuutti Kotivuori
2003-12-16 13:28 ` Oleg Trott
2003-12-18  0:15   ` Nuutti Kotivuori
2003-12-16 13:48 ` Ville-Pertti Keinonen
2003-12-16 15:41   ` Kenneth Knowles
2003-12-16 16:45     ` Richard Jones
2003-12-16 18:36       ` Ville-Pertti Keinonen
2003-12-16 18:42 ` Brian Hurt
2003-12-16 18:10   ` Dustin Sallings
2003-12-17  6:30     ` ijtrotts
2003-12-17  8:13       ` Dustin Sallings
2003-12-17 10:35       ` Falk Hueffner
2003-12-17 19:14         ` Pierre Weis
2003-12-17 19:32           ` Falk Hueffner
2003-12-17 20:04           ` David Brown
2003-12-18  1:14           ` Nicolas Cannasse
2003-12-18  5:31             ` David Brown
2003-12-18  7:05             ` Brian Hurt
2003-12-18  6:45               ` David Brown
2003-12-18 18:44             ` brogoff [this message]
2003-12-17 19:42         ` brogoff
2003-12-19 13:39           ` skaller
2003-12-18  0:51       ` Nuutti Kotivuori
2003-12-16 18:06 Kevin S. Millikin
2003-12-18 22:08 Ker Lutyn

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.44.0312181008040.32105-100000@grace.speakeasy.net \
    --to=brogoff@speakeasy.net \
    --cc=caml-list@inria.fr \
    --cc=falk.hueffner@student.uni-tuebingen.de \
    --cc=pierre.weis@inria.fr \
    --cc=warplayer@free.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).