caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Diego Olivier FERNANDEZ PONS <diego.fernandez_pons@etu.upmc.fr>
To: caml-list@inria.fr
Subject: Type inference inside exceptions ?
Date: Fri, 06 Oct 2006 20:16:47 +0200	[thread overview]
Message-ID: <20061006201647.1a88vj0tkockc4k8@webmail.etu.upmc.fr> (raw)

     Bonjour,

I would like the type-checker to infer the type inside exceptions (or  
at least to help me in the "guess a type and test" loop).

More specifically, here is my problem:

I have a program that computes the optimal solution of the minimal  
cardinality subset-sum problem with multiplicities. In simple words it  
gives the minimum number of coins you need to reach a given amount of  
money.

val smc : int -> int list -> int list list * int = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
- : int list list * int =
([[75; 75; 75; 1]; [122; 64; 10; 10; 10; 10]; [198; 10; 10; 5; 1; 1; 1]],
  198105)

The programs gives all the solutions it found, the last one being the  
optimal (with the total number of backtracks). The best solution is  
kept by side-effects on a global variable.

type environment = {
     mutable solutions : int list list;
     mutable backtracks : int;
     mutable card : int
   }

exception Fail

let rec min_card env = fun to_reach chosen candidates ->
   if (to_reach = 0) then
     match compare env.card (List.length chosen) with
       | n when n <= 0 ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | _ ->
	  env.solutions <- chosen :: env.solutions;
	  env.card <- List.length chosen;
	  raise Fail
   else
     match candidates with
       | [] ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | x :: tail when x > to_reach -> min_card env to_reach chosen tail
       | x :: tail ->
	  try
	    min_card env (to_reach - x) (x :: chosen) candidates
	  with Fail ->
	    min_card env to_reach chosen tail

let rec smc = fun to_reach list ->
   let env = { solutions = []; backtracks = 0; card = max_int } in
     try
       min_card env to_reach [] (List.sort (fun x y -> compare y x) list)
   with Fail -> (List.map List.rev env.solutions, env.backtracks)

Now I want the program not to return all the solutions but only the  
first solution it found and a list of continuations that I can launch  
again if a better solution is required.

Therefore I add a second exception
type continuation = ...
exception Solution of int * continuation list

And I collect the continuations from the try ... catch when the left  
tree happens to contain a solution

try
    explore left subtree
with
   | Fail -> explore right subtree
   | Solution (s, cont) ->
     let c = function () -> explore right subtree in
       raise Solution (s, c :: cont)

Not knowing the type of the continuation, I just tried unit -> int

Here is the detailed code

type continuation = unit -> int
exception Solution of int * continuation list

let rec min_card env = fun to_reach chosen candidates ->
   if (to_reach = 0) then
     match compare env.card (List.length chosen) with
       | n when n <= 0 ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | _ ->
	  env.solutions <- chosen :: env.solutions;
	  env.card <- List.length chosen;
	  raise (Solution (List.length chosen, []))
   else
     match candidates with
       | [] ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | x :: tail when x > to_reach -> min_card env to_reach chosen tail
       | x :: tail ->
	  try
	    min_card env (to_reach - x) (x :: chosen) candidates
	  with
	    | Fail -> min_card env to_reach chosen tail
	    | Solution (s, continuation) ->
		let c = fun () -> min_card env to_reach chosen tail in
		  raise (Solution (s, (c :: continuation)))

I first wrap without catching the exceptions and test

let smc = fun to_reach list ->
   let env = { solutions = []; backtracks = 0; card = max_int } in
       min_card env to_reach [] list

# val smc : int -> int list -> int = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
Exception: Solution (7, [<fun>; <fun>; <fun>; <fun>; <fun>; <fun>; <fun>]

Seems correct.

Now I try to extract the integer

let smc = fun to_reach list ->
   try
     let env = { solutions = []; backtracks = 0; card = max_int } in
       min_card env to_reach [] list
   with Solution (c, l) -> c

# val smc : int -> int list -> int = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
- : int = 7

Correct.

Now I try to extract the continuation list

let smc = fun to_reach list ->
   let env = { solutions = []; backtracks = 0; card = max_int } in
     try
       min_card env to_reach [] list
     with Solution (c, l) -> l

This expression has type continuation list but is here used with type int

Ok. I have to correct the type of continuation by hand

lets try [type continuation = unit -> (unit -> int)]

This expression has type continuation list but is here used with type
   unit -> int

lets try [type continuation = Cont of (unit -> continuation)]
and [let c = Cont (fun () -> ... ) in raise Solution (s, c :: cont)]

This expression has type continuation list but is here used with type
   continuation

lets try [type continuation = Cont of (unit -> continuation list)]

# val smc : int -> int list -> continuation list = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
- : continuation list =
[Cont <fun>; Cont <fun>; Cont <fun>; Cont <fun>; Cont <fun>; Cont <fun>;
  Cont <fun>]

Great ! Now I want the solution, its cardinality and the continuation list

lets try ...

          Diego Olivier


             reply	other threads:[~2006-10-06 18:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-10-06 18:16 Diego Olivier FERNANDEZ PONS [this message]
2006-10-06 20:20 ` [Caml-list] " ketty .
2006-10-10 10:28   ` Diego Olivier FERNANDEZ PONS
2006-10-11 22:50 ` Stéphane Glondu
2006-10-13 12:23   ` Diego Olivier FERNANDEZ PONS
2006-10-13 12:42     ` Pietro Abate
2006-10-14 19:56       ` Reordering continuations (was :Type inference inside exceptions ?) Diego Olivier FERNANDEZ PONS
2006-10-16  9:25         ` [Caml-list] " Diego Olivier FERNANDEZ PONS
2006-10-17 12:33           ` Diego Olivier FERNANDEZ PONS
2006-10-19  7:32             ` Looking for references to usage of ocaml in data mining, knowleadge discovery, etc  Dr. Axel Poigné 
2006-10-19 14:06               ` [Caml-list] " Markus Mottl

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=20061006201647.1a88vj0tkockc4k8@webmail.etu.upmc.fr \
    --to=diego.fernandez_pons@etu.upmc.fr \
    --cc=caml-list@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).