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] Help me find this pdf
Date: Thu, 18 Oct 2007 18:18:31 +0100	[thread overview]
Message-ID: <200710181818.31430.jon@ffconsultancy.com> (raw)
In-Reply-To: <47176C28.1090509@janestcapital.com>

On Thursday 18 October 2007 15:22:32 Brian Hurt wrote:
> You have to explicitly force the lazy value first-

If you force all lazy values before the pattern match then you are doing eager 
evaluation, not lazy. Moreover, you must also generate an auxiliary data 
structure to store the forced values in order to pattern match over them.

> but other than it being explicit,

And not lazy.

> this is no different from other languages that implicitly force the value
> for you. 

On the contrary, it fails to achieve laziness.

> Well, Haskell has an option where a pattern match can always succeed that
> doesn't necessarily force the lazy value

Exactly. Not "necessarily forcing" the lazy value is the essence of lazy 
evaluation and the only point to my suggestion.

> (I forget what it's called at the moment), but baring that... 

You can't ignore that: its the whole point! :-)

Consider a function that concatenates adjacent "Some _" values in a list:

# let rec f = function
    | [] -> []
    | Some x :: Some y :: t -> f(Some(x @ y) :: t)
    | h :: t -> h :: f t;;
val f : 'a list option list -> 'a list option list = <fun>
# f [Some [1]; Some [2;3]; None; Some [4;5]];;
- : int list option list = [Some [1; 2; 3]; None; Some [4; 5]]

Thanks to pattern matching, this solution is almost as beautiful as my wife.

An equivalent with lazy lists might be:

# type 'a llist = Nil | Cons of 'a * 'a llist lazy_t;;

# let rec f = function
    | Nil -> Nil
    | Cons(None, t) -> Cons(None, lazy(f(Lazy.force t)))
    | Cons(Some x as h, t) ->
        match Lazy.force t with
        | Nil -> Cons(h, lazy Nil)
        | Cons(None, t) -> Cons(h, lazy(Cons(None, lazy(f(Lazy.force t)))))
        | Cons(Some y, t) -> Cons(Some(x @ y), lazy(f(Lazy.force t)));;
val f : 'a list option llist -> 'a list option llist = <fun>

# let rec forces = function
    | Nil -> []
    | Cons(h, t) -> h :: forces(Lazy.force t);;
val forces : 'a llist -> 'a list = <fun>

# forces(f(Cons(Some [1], lazy(Cons(Some [2;3], lazy(Cons(None, lazy(Cons(Some 
[4;5], lazy Nil)))))))));;
- : int list option list = [Some [1; 2; 3]; None; Some [4; 5]]

Because you can't pattern match over lazy values, this solution is about as 
beautiful as my first girlfriend.

This is no freakishly theoretical problem either, it crops up whenever I want 
to destructure a collection as a sequence. You can use an unfold but that 
only buys you 1 element look ahead whereas the power of pattern matching 
stems from its ability to dispatch based upon destructuring to arbitrary 
depths.

If it were possible to pattern match over lazy values, you would simply write 
a to_lazylist function in the module of each container and pattern match over 
its result to dissect any container with minimal copying.

In this case, you would write:

# let rec f = function
    | Nil -> []
    | Cons(Some x, lazy(Cons(Some y, lazy t))) -> f(Some(x @ y) :: t)
    | Cons(h, lazy t) -> h :: f t;;
val f : 'a list option llist -> 'a list option llist = <fun>

You could even define the primitives in terms of pattern matching:

  let force (lazy x) = x

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?e


  parent reply	other threads:[~2007-10-18 21:49 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-18  9:52 Tom
2007-10-18 10:33 ` [Caml-list] " skaller
2007-10-18 11:01   ` Andreas Rossberg
2007-10-18 12:25 ` Jon Harrop
2007-10-18 12:40   ` Arnaud Spiwack
2007-10-18 13:17     ` Jon Harrop
2007-10-18 15:15       ` Till Varoquaux
2007-10-18 12:46   ` Jacques Garrigue
2007-10-18 13:57     ` Jon Harrop
2007-10-18 14:22       ` Brian Hurt
2007-10-18 14:52         ` Robert Fischer
2007-10-18 15:04           ` Eric Cooper
2007-10-18 17:18         ` Jon Harrop [this message]
2007-10-19  1:16           ` skaller
2007-10-19  5:09           ` Bárður Árantsson
2007-10-19  5:23             ` [Caml-list] " Erik de Castro Lopo
2007-10-19  5:46               ` Bárður Árantsson
2007-10-19 12:25               ` [Caml-list] " Christophe Raffalli
2007-10-19 12:47                 ` Luc Maranget
2007-10-20 14:26                   ` Christophe Raffalli
2007-10-19 14:48                 ` Robert Fischer
2007-10-19 21:43                   ` Andreas Rossberg
2007-10-19 21:51                     ` Robert Fischer
2007-10-20 13:10                       ` Andreas Rossberg
2007-10-19 23:10                     ` Jon Harrop
2007-10-20  1:13                       ` skaller
2007-10-20  6:36                         ` Tom
2007-10-21 11:17                           ` skaller
2007-10-19  8:55             ` Zheng Li
2007-10-19 22:27             ` [Caml-list] " Jon Harrop
2007-10-19 13:00           ` [Caml-list] " Brian Hurt
2007-10-19 13:49             ` Loup Vaillant
2007-10-19 14:41               ` Zheng Li
2007-10-19 23:09             ` [Caml-list] " Jon Harrop
2007-10-18 20:07   ` Tom
2007-10-19  0:59     ` skaller
2007-10-18 20:48 ` Lauri Alanko

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=200710181818.31430.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).