caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Amb
@ 2007-02-09 21:31 Jonathan Bryant
  2007-02-09 21:55 ` [Caml-list] Amb Brian Hurt
  0 siblings, 1 reply; 7+ messages in thread
From: Jonathan Bryant @ 2007-02-09 21:31 UTC (permalink / raw)
  To: caml-list

All,

I'm having to learn Scheme for a class, and I ran across a simple but  
really useful predicate: amb.  More info on this can be found here:  
http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z- 
H-16.html#node_chap_14

Since OCaml doesn't seem to have this, I implemented it:

exception Amb
let rec amb l = match l with
| [] -> raise Amb
| h::t -> try h () with Amb -> amb t

let amb l = try Some (amb l) with Amb -> None

(* val amb : (unit -> 'a) list -> 'a option *)

I know things are not added to the standard library lightly, but it  
seems that this one function doesn't really need it's own library and  
could be easily added somewhere.  It just seems that this would be a  
small but convenient addition.

--Jonathan Bryant


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Amb
  2007-02-09 21:31 Amb Jonathan Bryant
@ 2007-02-09 21:55 ` Brian Hurt
  2007-02-09 22:12   ` Andrej Bauer
  2007-02-10  0:01   ` Jon Harrop
  0 siblings, 2 replies; 7+ messages in thread
From: Brian Hurt @ 2007-02-09 21:55 UTC (permalink / raw)
  To: Jonathan Bryant; +Cc: caml-list

Jonathan Bryant wrote:

> All,
>
> I'm having to learn Scheme for a class, and I ran across a simple but  
> really useful predicate: amb.  More info on this can be found here:  
> http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z- 
> H-16.html#node_chap_14
>
> Since OCaml doesn't seem to have this, I implemented it:
>
> exception Amb
> let rec amb l = match l with
> | [] -> raise Amb
> | h::t -> try h () with Amb -> amb t
>
> let amb l = try Some (amb l) with Amb -> None
>
You might try:
let rec amb = function
    | [] -> None
    | h :: t ->
       let r =
          try
             Some(h ())
          with
             | _ -> None
       in
       match r with
       | None -> amb t
       | Some(_) as e -> e
;;

As a slightly better implementation.

Brian


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Amb
  2007-02-09 21:55 ` [Caml-list] Amb Brian Hurt
@ 2007-02-09 22:12   ` Andrej Bauer
  2007-02-09 22:42     ` Tom
  2007-02-10  0:01   ` Jon Harrop
  1 sibling, 1 reply; 7+ messages in thread
From: Andrej Bauer @ 2007-02-09 22:12 UTC (permalink / raw)
  To: Brian Hurt; +Cc: Jonathan Bryant, caml-list

To make this thread worthy of a non-beginner ocaml list, let me point 
out that amb is supposed to work as an _angelic_ nondeterministic choice 
operator. This means it must choose a value that, if at all possible, 
leads to successful completion of the computation. In particular, the 
piece of code (assuming exception Amb denotes failure)

   if (abm [(fun _ -> false); (fun _ -> true)]) then
     7
   else
     (raise Amb)

should return 7, i.e., the amb inside the conditional should "know" (be 
told by an angel) that the right choice is the second element of the 
list because it leads to 7, whereas chosing the first one leads to failure.

I am afraid the implementation given by Jonathan does not satisfy this 
condition. And I don't see how to make it work. The scheme 
implementation involves callcc magic. If anyone knows a reasonable 
implementation of amb, I'd be interested to know.

Andrej


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Amb
  2007-02-09 22:12   ` Andrej Bauer
@ 2007-02-09 22:42     ` Tom
  2007-02-10  0:03       ` Jon Harrop
  0 siblings, 1 reply; 7+ messages in thread
From: Tom @ 2007-02-09 22:42 UTC (permalink / raw)
  To: Andrej.Bauer; +Cc: Brian Hurt, Jonathan Bryant, caml-list

[-- Attachment #1: Type: text/plain, Size: 410 bytes --]

What would amb do with this kind of program:

let f_out = open_out "file1.tmp";;
output_string f_out "good\n";;
close_out;;

if (abm [(fun _ -> false); (fun _ -> true)]) then
     let f_in = open_in "file1.tmp" in
     if input_line f_in = "good" then exit 0 (* SUCCESS *)
     else raise Amb
else
      let f_out2 = open_out_get [Open_trunc] 0o777 "file1.tmp" in
      output_string f_out2 "bad\n"


?

- Tom

[-- Attachment #2: Type: text/html, Size: 643 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Amb
  2007-02-09 21:55 ` [Caml-list] Amb Brian Hurt
  2007-02-09 22:12   ` Andrej Bauer
@ 2007-02-10  0:01   ` Jon Harrop
  2007-02-10  1:12     ` Brian Hurt
  1 sibling, 1 reply; 7+ messages in thread
From: Jon Harrop @ 2007-02-10  0:01 UTC (permalink / raw)
  To: caml-list

On Friday 09 February 2007 21:55, Brian Hurt wrote:
> let rec amb = function
>
>     | [] -> None
>     | h :: t ->
>
>        let r =
>           try
>              Some(h ())
>           with
>
>              | _ -> None
>
>        in
>        match r with
>
>        | None -> amb t
>        | Some(_) as e -> e
>
> As a slightly better implementation.

I think you're trying to box the returned value in order to evade non-tail 
recursion but the OPs function was actually already tail recursive because 
the recursive call to "amb" occurs outside the try..with.

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


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Amb
  2007-02-09 22:42     ` Tom
@ 2007-02-10  0:03       ` Jon Harrop
  0 siblings, 0 replies; 7+ messages in thread
From: Jon Harrop @ 2007-02-10  0:03 UTC (permalink / raw)
  To: caml-list

On Friday 09 February 2007 22:42, Tom wrote:
> What would amb do with this kind of program:
>
> let f_out = open_out "file1.tmp";;
> output_string f_out "good\n";;
> close_out;;
>
> if (abm [(fun _ -> false); (fun _ -> true)]) then
>      let f_in = open_in "file1.tmp" in
>      if input_line f_in = "good" then exit 0 (* SUCCESS *)
>      else raise Amb
> else
>       let f_out2 = open_out_get [Open_trunc] 0o777 "file1.tmp" in
>       output_string f_out2 "bad\n"

Spawn parallel universes?

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


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Caml-list] Amb
  2007-02-10  0:01   ` Jon Harrop
@ 2007-02-10  1:12     ` Brian Hurt
  0 siblings, 0 replies; 7+ messages in thread
From: Brian Hurt @ 2007-02-10  1:12 UTC (permalink / raw)
  To: Jon Harrop; +Cc: caml-list



On Sat, 10 Feb 2007, Jon Harrop wrote:

> On Friday 09 February 2007 21:55, Brian Hurt wrote:
>> let rec amb = function
>>
>>     | [] -> None
>>     | h :: t ->
>>
>>        let r =
>>           try
>>              Some(h ())
>>           with
>>
>>              | _ -> None
>>
>>        in
>>        match r with
>>
>>        | None -> amb t
>>        | Some(_) as e -> e
>>
>> As a slightly better implementation.
>
> I think you're trying to box the returned value in order to evade non-tail
> recursion but the OPs function was actually already tail recursive because
> the recursive call to "amb" occurs outside the try..with.

He was doing the boxing on the return as well.  And note, in the above 
code I only box once.

Brian


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-02-10  1:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-09 21:31 Amb Jonathan Bryant
2007-02-09 21:55 ` [Caml-list] Amb Brian Hurt
2007-02-09 22:12   ` Andrej Bauer
2007-02-09 22:42     ` Tom
2007-02-10  0:03       ` Jon Harrop
2007-02-10  0:01   ` Jon Harrop
2007-02-10  1:12     ` Brian Hurt

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