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
next prev 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).