caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Locally-polymorphic exceptions [was: folding over a file]
@ 2007-10-03  8:35 oleg
  2007-10-03 11:27 ` kirillkh
  0 siblings, 1 reply; 41+ messages in thread
From: oleg @ 2007-10-03  8:35 UTC (permalink / raw)
  To: kirillkh; +Cc: caml-list


kirillkh wrote
> Is there a way to instantiate an exception with a value of unspecified type
> and then do explicit casting on catch?

Surprisingly, the answer in many (or all?) cases is yes. The answer is
definitely yes in the case when we need to define an exception local
to a polymorphic function. Incidentally, SML permits declarations of
such local exceptions whose type is tied to that of the host
polymorphic function. That feature has been used to implement
delimited continuations. Perhaps unsurprisingly, delimited
continuations can be used to implement such locally-polymorphic
exceptions.

The recent thread gave a good motivation for locally polymorphic
exceptions: writing a library function fold_file. The following code
has been proposed.

> exception Done of 'a
>
>  let fold_file (file: in_channel)
>               (read_func: in_channel->'a)
>               (elem_func: 'a->'b->'b)
>               (seed: 'b) =
>   let rec loop prev_val =
>     let input =
>       try read_func file
>       with End_of_file -> raise (Done prev_val)
>     in
>       let combined_val = elem_func input prev_val in
>       loop combined_val
>   in
>     try loop seed with Done x -> x

Alas, the compiler does not accept the exception declaration, because
the declaration says that the exception should carry a value of all
types. There is no value that belongs to all types (and if it were, it
wouldn't be useful). But we don't actually need the value of all
types. We need the value of our Done exception to have the same type
as the result of the polymorphic function fold_file. We should have
declared the exception Done _inside_ fold_file. And that can be done:
Delimcc.prompt is precisely this type of `local exceptions'.

So, we can implement fold_file, by slightly adjusting the above code:

let fold_file (file: in_channel)
              (read_func: in_channel->'a)
              (elem_func: 'a->'b->'b)
              (seed: 'b) =
  let result = new_prompt () in (* here is our local exn declaration *)
  let rec loop prev_val =
     let input =
       try read_func file
       with End_of_file -> abort result prev_val
     in
       let combined_val = elem_func input prev_val in
       loop combined_val
   in
     push_prompt result (fun () -> loop seed)
;;

(*
val fold_file :
  in_channel -> (in_channel -> 'a) -> ('a -> 'b -> 'b) -> 'b -> 'b = <fun>
*)

let line_count filename =
   let f = open_in filename in
   let counter _ count = count + 1 in
   fold_file f input_line counter 0;;

(*
 val line_count : string -> int = <fun>
*)

let test = line_count "/etc/motd";;
(*
 val test : int = 24
*)


The analogy between exceptions and delimited continuations is
profound: in fact, delimited continuations are implemented in terms of
exceptions. Abort is truly raise. Well, observationally. The current
delimcc library tried to follow Dybvig, Sabry and Peyton-Jones
interface -- which, being minimalistic, did not include abort as a
primitive. We have to implement abort in terms of take_subcont, which
is wasteful as we save the captured continuation for no good
reason. Internally, the library does have an abort primitive, and it
indeed works in the same way as raise.


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

end of thread, other threads:[~2007-10-05  2:49 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-03  8:35 Locally-polymorphic exceptions [was: folding over a file] oleg
2007-10-03 11:27 ` kirillkh
2007-10-03 11:48   ` [Caml-list] " Daniel de Rauglaudre
2007-10-03 12:19     ` kirillkh
2007-10-03 12:32       ` Daniel de Rauglaudre
2007-10-03 14:34         ` kirillkh
2007-10-03 20:39   ` Christophe Raffalli
2007-10-03 22:50     ` Unsoundness is essential skaller
2007-10-03 23:13       ` [Caml-list] " Jacques Carette
2007-10-04  1:24         ` skaller
2007-10-04 11:26           ` David Allsopp
2007-10-04 12:45             ` Vincent Hanquez
2007-10-04 15:07               ` skaller
2007-10-03 23:13       ` Vincent Aravantinos
2007-10-04  1:49         ` skaller
2007-10-03 23:28       ` Joshua D. Guttman
2007-10-04  1:52         ` skaller
2007-10-04  2:35           ` Brian Hurt
2007-10-04  7:46           ` Christophe Raffalli
2007-10-04  8:56             ` Arnaud Spiwack
2007-10-04 14:49               ` skaller
2007-10-04 15:00                 ` Harrison, John R
2007-10-04 15:29                 ` Andrej Bauer
2007-10-04 16:25                   ` skaller
2007-10-04 18:17                     ` Arnaud Spiwack
2007-10-04 20:54                       ` skaller
2007-10-04 22:24                         ` Arnaud Spiwack
2007-10-04 16:37                   ` skaller
2007-10-04 18:59                     ` Christophe Raffalli
2007-10-04 15:04               ` Andrej Bauer
2007-10-04 15:57                 ` Christophe Raffalli
2007-10-04 16:03                 ` skaller
2007-10-04 20:02                   ` Ken Rose
2007-10-04 21:00                     ` skaller
2007-10-04 15:31       ` Lukasz Stafiniak
2007-10-04 17:56       ` rossberg
2007-10-04 19:56         ` skaller
2007-10-04 21:07           ` rossberg
2007-10-04 22:23             ` skaller
2007-10-05  2:48               ` Bárður Árantsson
2007-10-04  2:16   ` Locally-polymorphic exceptions [was: folding over a file] oleg

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