How to combine a list of modules?

I would like to know if it is possible to reduce a list of first class modules into one modules. The goal would be to generate the cartesian product of an arbitrary number of algebraic structures.
For instance, given a signature SGroup:

module type SGroup = sig 
    type t 
    val add : t -> t -> t
end

and a functor

module Product (G1:SGroup)(G2:SGroup) : SGroup = struct
    type t = G1.t * G2.t
    let add (x1,x2) (y1,y2) = (G1.add x1 y1,G2.add x2 y2) 
end

I can define a list of first class modules:

let sgroups_list =
  [
    (module struct
      type t = int
      let add = ( + )
    end : Group);
    (module struct
      type t = float

      let add = (+.)
    end : Group)
  ]

Is there a way to “fold” such (non-empty) list of first class modules using Product?

Yes:

let fold l = match l with
  | [] -> failwith "Empty list: cannot start"
  | first :: rest ->
    List.fold_left (fun (module Acc : SGroup) (module Elt : SGroup) ->
        (module Product (Acc) (Elt) : SGroup))
      first rest

Is the question how you can get Product into a form that you can pass it to List.fold_left or similar folding functions? The trick is to write a function (not a functor) that takes in first-class modules, unpacks them into ordinary modules, applies the functor, and then re-packs the result as another first-class module:

let product (module A : SGroup) (module B : SGroup) = (module Product (A) (B) : SGroup)