module N9 = struct
  let n:int = 9
end

module N8 = struct
  let n:int = 8
end

module RangeInv = struct
  let rec f (a:int) : int list =
    if a=0 then [] else a::(f (a-1))
end

module Range = struct
  let rec concat (l1:int list) (l2:int list) : int list =
    match l1 with
        [] -> l2
      | x::s -> x::(concat s l2)
  let rec f (a:int) : int list =
    if a=0 then [] else concat (f (a-1)) (a::[])
end

module List (A : sig val f : unit -> int -> int list end) (B : sig val n : int end) = struct
  let l:int list = A.f () B.n
end

module List2
  (A : sig val f : int -> int list end)
  (B : sig val f : int -> int list end)
  (C : sig val n : int end) (* (* Ce premier C ne sert à rien -> vérification importante !! *) et les commentaires sont imbriqués !! *)
  (C : sig val n : int end) = struct
  
  module A2 = struct
    let f (a:unit) (b:int) : int list = A.f b
  end

  module B2 = struct
    let f (a:unit) (b:int) : int list = B.f b
  end

  module K = List(A2)
  module A = K(C)
  module B = List(B2)(C)

  let rec print (l1:int list) (l2:int list) : unit = match l1 with
    | [] -> () 
    | x::s -> print_int x;
        let s2 = (match l2 with [] -> [] | x::s -> print_int x; s) in
            print_newline (); print s s2

  let print_auto (a:unit) : unit = print A.l B.l

end

module K = List2(Range)(RangeInv)(N8)
module A = K(N9)

let () = A.print A.B.l A.A.l ; print_newline ()

module B = List2(RangeInv)(Range)(N9)(N8)

let () = A.print A.B.l B.B.l ; print_newline ()
let () = B.print_auto ()
