(** Ce fichier type bien, montrant comment le type ('a,'r) fmt fonctionne.
  * Le foncteur T indique ensuite comment une implémentation de PRINTF est
  * censée se comporter. L'exercice est de réaliser une telle implémentation
  * et de la tester avec T. *)

module type PRINTF = sig

  type ('a,'r) fmt
  (** En pratique on va garantir que 'a = T1 -> ... -> Tn -> 'r
    * où les Ti sont soit int soit string. *)

  val fmt_i : (int -> 'r, 'r) fmt
  val fmt_lit : string -> ('r,'r) fmt
  val fmt_concat : ('a,'b) fmt -> ('b,'r) fmt -> ('a,'r) fmt

  val print : ('a,unit) fmt -> 'a

end

(** Un module de test. *)
module T (P:PRINTF) = struct

  open P

  let (^) = fmt_concat

  let () =
    (* Doit afficher "12\nfoo\n42...24\n". *)
    print fmt_i 12 ;
    print (fmt_lit "\nfoo\n") ;
    print (fmt_i ^ fmt_lit "..." ^ fmt_i ^ fmt_lit "\n") 42 24

end