diff --git a/colibri2/theories/array/array.ml b/colibri2/theories/array/array.ml
index aec812e830bd936a4073cb3b310cf596905973a7..a41d097e1529495d84d20876cb1668a9ea58cf20 100644
--- a/colibri2/theories/array/array.ml
+++ b/colibri2/theories/array/array.ml
@@ -119,15 +119,9 @@ module Builtin = struct
         | _ -> `Not_found)
 end
 
-(* Helper functions  *)
-let is_array env n =
-  let res =
-    Ground.Ty.S.exists
-      (function { app = { builtin = Expr.Array; _ }; _ } -> true | _ -> false)
-      (Ground.tys env n)
-  in
-  Debug.dprintf3 debug "is_array %a: %b" Node.pp n res;
-  res
+let mk_subst term_l ty_l =
+  Ground.Subst.
+    { term = Expr.Term.Var.M.of_list term_l; ty = Expr.Ty.Var.M.of_list ty_l }
 
 let is_foreign env n =
   let res =
@@ -334,23 +328,14 @@ module Theory = struct
     let l = if !extended_comb then (const_pattern, const_run) :: l else l in
     List.iter (fun (p, r) -> InvertedPath.add_callback env p r) l
 
-  let new_array env f =
-    let s = Ground.sem f in
-    let s_index_ty = List.hd s.ty.args in
-    let s_value_ty = List.hd (List.tl s.ty.args) in
+  let new_array env s_index_ty s_value_ty f =
     (* Extensionality rule ext: a, b ⇒ (a = b) ⋁ (a[k] ≠ b[k]) *)
     if not !restrict_ext then (
       Datastructure.Push.iter db env ~f:(fun f2 ->
           let subst =
-            Ground.Subst.
-              {
-                term =
-                  Expr.Term.Var.M.of_list
-                    [ (va, Ground.node f2); (vb, Ground.node f) ];
-                ty =
-                  Expr.Ty.Var.M.of_list
-                    [ (ind_ty_var, s_index_ty); (val_ty_var, s_value_ty) ];
-              }
+            mk_subst
+              [ (va, Ground.node f2); (vb, Ground.node f) ]
+              [ (ind_ty_var, s_index_ty); (val_ty_var, s_value_ty) ]
           in
           Debug.dprintf2 debug "Found ext with %a" Ground.Subst.pp subst;
           let n = distinct_term_node ~subst env ta tb in
@@ -360,13 +345,9 @@ module Theory = struct
     (* 𝝐𝛿: a |> a[𝝐] = 𝛿 *)
     if !extended_comb then (
       let subst =
-        Ground.Subst.
-          {
-            term = Expr.Term.Var.M.of_list [ (va, Ground.node f) ];
-            ty =
-              Expr.Ty.Var.M.of_list
-                [ (ind_ty_var, s_index_ty); (val_ty_var, s_value_ty) ];
-          }
+        mk_subst
+          [ (va, Ground.node f) ]
+          [ (ind_ty_var, s_index_ty); (val_ty_var, s_value_ty) ]
       in
       let epsilon_app = apply_def_index ta in
       let delta_app = apply_def_value ta in
@@ -380,24 +361,41 @@ end
 
 let converter env (f : Ground.t) =
   let s = Ground.sem f in
-  (match s.ty with
-  | { app = { builtin = Expr.Array; _ }; _ } ->
-      (* apply rules that apply on all arrays *)
-      Theory.new_array env f
-  | _ -> ());
+  let f_is_array =
+    match s.ty with
+    | { app = { builtin = Expr.Array; _ }; args = [ s_ind_ty; s_val_ty ]; _ } ->
+        Theory.new_array env s_ind_ty s_val_ty f;
+        true
+    | _ -> false
+  in
   match s with
-  | { app = { builtin = Expr.Base; _ }; args; _ } ->
+  | { app = { builtin = Expr.Base; id_ty; _ }; args; tyargs; _ } ->
       let fn = Ground.node f in
       if IArray.is_empty args then (
-        if !restrict_aup && is_array env fn then
+        if !restrict_aup && f_is_array then
           (* update of the Linearity domain *)
           Linearity_dom.upd_dom env fn Empty)
       else if !restrict_ext then
         (* update of the Foreign domain *)
-        IArray.iter
-          ~f:(fun n ->
-            if is_array env n then Foreign_dom.set_dom env n IsForeign)
-          args
+        let subst, param_tys =
+          match id_ty.ty_descr with
+          | Pi (tyvl, { ty_descr = Expr.Arrow (ptys, _); _ }) ->
+              ( List.fold_left2
+                  (fun m k v -> Expr.Ty.Var.M.add k v m)
+                  Expr.Ty.Var.M.empty tyvl tyargs,
+                ptys )
+          | Expr.Arrow (ptys, _) -> (Expr.Ty.Var.M.empty, ptys)
+          | _ -> (Expr.Ty.Var.M.empty, [])
+        in
+        if param_tys <> [] then
+          (* should be always true *)
+          IArray.iteri
+            ~f:(fun i n ->
+              match Ground.Ty.convert subst (List.nth param_tys i) with
+              | { app = { builtin = Expr.Array; _ }; _ } ->
+                  Foreign_dom.set_dom env n IsForeign
+              | _ -> ())
+            args
   | {
    app = { builtin = Expr.Select; _ };
    args;
@@ -408,20 +406,21 @@ let converter env (f : Ground.t) =
       Egraph.register env a;
       Egraph.register env i;
       (* update of the Foreign domain *)
-      if !restrict_ext && is_array env i then
-        Foreign_dom.set_dom env i IsForeign;
+      if
+        !restrict_ext
+        &&
+        match s_ind_ty with
+        | { app = { builtin = Expr.Array; _ }; _ } -> true
+        | _ -> false
+      then Foreign_dom.set_dom env i IsForeign;
       (* application of the `not default` rule 𝝐≠: v = a[i], i ≠ 𝝐 |> i ≠ 𝝐 *)
       (* should only be applied if the index sort is infinite,
          otherwise the blast rule should be applied *)
       if !extended_comb then (
         let subst =
-          Ground.Subst.
-            {
-              term = Expr.Term.Var.M.of_list [ (Theory.va, a); (Theory.vi, i) ];
-              ty =
-                Expr.Ty.Var.M.of_list
-                  [ (ind_ty_var, s_ind_ty); (val_ty_var, s_val_ty) ];
-            }
+          mk_subst
+            [ (Theory.va, a); (Theory.vi, i) ]
+            [ (ind_ty_var, s_ind_ty); (val_ty_var, s_val_ty) ]
         in
         let eps_term = apply_def_index Theory.ta in
         let eps_node = convert ~subst env eps_term in
@@ -447,15 +446,9 @@ let converter env (f : Ground.t) =
       if !restrict_aup then Linearity_dom.upd_dom env (Ground.node f) (Linear a);
       (* application of the `idx` rule *)
       let subst =
-        Ground.Subst.
-          {
-            term =
-              Expr.Term.Var.M.of_list
-                [ (Theory.va, a); (Theory.vk, k); (Theory.vv, v) ];
-            ty =
-              Expr.Ty.Var.M.of_list
-                [ (ind_ty_var, s_ind_ty); (val_ty_var, s_val_ty) ];
-          }
+        mk_subst
+          [ (Theory.va, a); (Theory.vk, k); (Theory.vv, v) ]
+          [ (ind_ty_var, s_ind_ty); (val_ty_var, s_val_ty) ]
       in
       let store_term = Expr.Term.store Theory.ta Theory.tk Theory.tv in
       let rn =
@@ -486,13 +479,7 @@ let converter env (f : Ground.t) =
       Egraph.register env v;
       (* application of the `K𝛿` rule *)
       if !default_values then (
-        let subst =
-          Ground.Subst.
-            {
-              term = Expr.Term.Var.M.of_list [ (Theory.vv, v) ];
-              ty = Expr.Ty.Var.M.of_list [ (val_ty_var, s_val_ty) ];
-            }
-        in
+        let subst = mk_subst [ (Theory.vv, v) ] [ (val_ty_var, s_val_ty) ] in
         let eq_node =
           convert ~subst env
             (Expr.Term.eq (apply_def_value (apply_const Theory.tv)) Theory.tv)