let print_list l =
  Printf.printf "[%s]\n" (String.concat "," (List.map string_of_int l))

let return x ~sk ~fk = sk x fk
let fail ~sk ~fk = fk ()
let orelse m n ~sk ~fk = m ~sk ~fk:(fun () -> n ~sk ~fk)
let andthen m n ~sk ~fk = m ~sk:(fun x k -> n x ~sk ~fk:k) ~fk

(** [f max target] énumère les listes (triées) d'entiers [2<=i<=max]
  * dont la somme fait [target]. On suppose [max <= target]. *)
let rec f max target =
  if target = 0 then return [] else
    if max = 1 then fail else
      (* On met [max] dans la liste, ou pas. *)
      orelse
        (andthen
           (f (min max (target-max)) (target-max))
           (fun l -> return (max::l)))
        (f (max-1) target)

let () =
  let fk () = () in
  let sk l k = print_list l ; k () in
    f 5 5 ~sk ~fk

(** Si on préfère, on peut se passer des combinateurs... *)
let rec f o n sk fk =
  if n = 0 then sk [] fk else
    if o=1 then fk () else
      f (min o (n-o)) (n-o)
        (fun s k -> sk (o::s) k)
        (fun () -> f (o-1) n sk fk)

let () =
  f 5 5 (fun l k -> print_list l ; k ()) ignore