diff --git a/examples/acasxu/acasxu.why b/examples/acasxu/acasxu.why
index e81f0fe6bd15019f59257a62b11e043249d1d732..1c438605cb3ebfb92a6ccf77f2bbf6dbfa6d6c32 100644
--- a/examples/acasxu/acasxu.why
+++ b/examples/acasxu/acasxu.why
@@ -9,9 +9,8 @@ theory ACASXU
   *)
 
   use ieee_float.Float64
-  use bool.Bool
   use int.Int
-  use vector.Vector
+  use types.Vector
   use model.Model
   use model.NN
 
diff --git a/examples/mnist/mnist.why b/examples/mnist/mnist.why
index 1ea347b25c742d6ca390ecf8a380826fd3ace9f8..1b87bf70c3b38d7a1bba967b0e99636bb9556750 100644
--- a/examples/mnist/mnist.why
+++ b/examples/mnist/mnist.why
@@ -1,7 +1,8 @@
 theory MNIST
 
   use ieee_float.Float64
-  use int.Int
+  use types.Float64WithBounds as Feature
+  use types.IntWithBounds as Label
   use model.Model
   use model.NN
   use dataset.CSV
@@ -10,22 +11,16 @@ theory MNIST
   constant model_filename: string
   constant dataset_filename: string
 
-  constant min_feature_value: t = (0.0:t)
-  constant max_feature_value: t = (1.0:t)
-
-  constant min_label : label_ = 0
-  constant max_label : label_ = 9
-
-  predicate valid_features (e: features) =
-    CSV.valid_features min_feature_value max_feature_value e
-
-  predicate valid_label (l: label_) =
-    CSV.valid_label min_label max_label l
+  constant label_bounds: Label.bounds =
+    Label.{ lower = 0; upper = 9 }
+  
+  constant feature_bounds: Feature.bounds =
+    Feature.{ lower = (0.0:t); upper = (1.0:t) }
 
   goal robustness:
     let nn = read_model model_filename in
     let dataset = read_dataset dataset_filename in
     let eps = (0.0100000000000000002081668171172168513294309377670288085937500000:t) in
-    robust valid_features valid_label nn dataset eps
+    robust feature_bounds label_bounds nn dataset eps
 
 end
diff --git a/src/interpretation.ml b/src/interpretation.ml
index cebfcb73b59cc0674c8d7d689be11a85dd16ae74..456b9c4074e0bb421a8c756049a0200700883c20 100644
--- a/src/interpretation.ml
+++ b/src/interpretation.ml
@@ -375,7 +375,7 @@ let caisar_builtins : caisar_env CRE.built_in_theories list =
   in
 
   [
-    ( [ "vector" ],
+    ( [ "types" ],
       "Vector",
       [],
       [
diff --git a/src/language.ml b/src/language.ml
index 8ac34c1f78962fbe1879cc81820964ec597f7a04..f5379b1ee2ac01e6f0382368f8d5174beeb56de1 100644
--- a/src/language.ml
+++ b/src/language.ml
@@ -165,7 +165,7 @@ let ty_float64_t env =
   Ty.ty_app (Theory.ns_find_ts th.th_export [ "t" ]) []
 
 let ty_vector env ty_elt =
-  let th = Env.read_theory env [ "vector" ] "Vector" in
+  let th = Env.read_theory env [ "types" ] "Vector" in
   Ty.ty_app (Theory.ns_find_ts th.th_export [ "vector" ]) [ ty_elt ]
 
 let create_vector =
diff --git a/stdlib/dataset.mlw b/stdlib/dataset.mlw
index 36eb79ad5d1f8cc5a5d7ff7bbf6397651b669e39..c91668f83b1396db9a0b5301c2d675a06949861f 100644
--- a/stdlib/dataset.mlw
+++ b/stdlib/dataset.mlw
@@ -26,7 +26,7 @@
 
 theory Dataset
 
-  use vector.Vector
+  use types.Vector
 
   type a
   type b
@@ -52,23 +52,14 @@ A dataset in CSV format is such that each element is given as:
 
 theory CSV
 
-  use int.Int
-  use ieee_float.Float64
-  use vector.Vector
+  use types.IntWithBounds as Label
+  use types.VectorFloat64 as FeatureVector
 
-  type label_ = int
-  type features = vector t
+  type label_ = Label.t
+  type features = FeatureVector.t
 
   clone export Dataset with type a = label_, type b = features
 
-  predicate valid_label (min_label: label_) (max_label: label_) (l: label_) =
-    min_label <= l <= max_label
-
-  predicate valid_features (min_feature_value: t) (max_feature_value: t)
-                           (e: features) =
-    forall v: index. valid_index e v ->
-      min_feature_value .<= e[v] .<= max_feature_value
-
   function infer_min_label (d: dataset) : label_
   function infer_max_label (d: dataset) : label_
 
diff --git a/stdlib/dune b/stdlib/dune
index 5b6ffda2752377bed92e86ac964d3c370cf8d66a..a4ec18d989d91c83846b2154a36d96b6c8f94416 100644
--- a/stdlib/dune
+++ b/stdlib/dune
@@ -2,5 +2,5 @@
  (section
   (site
    (caisar stdlib)))
- (files caisar.mlw robust.mlw vector.mlw model.mlw dataset.mlw)
+ (files caisar.mlw types.mlw robust.mlw model.mlw dataset.mlw)
  (package caisar))
diff --git a/stdlib/model.mlw b/stdlib/model.mlw
index a5b6cf2e68cf086b5a775e3584a681f7fd946049..d9cc3e609e4ca1f996d48c1510ac24094e564ae2 100644
--- a/stdlib/model.mlw
+++ b/stdlib/model.mlw
@@ -26,7 +26,7 @@
 
 theory Model
 
-  use vector.Vector
+  use types.Vector
 
   type kind
   type model 'kind
diff --git a/stdlib/robust.mlw b/stdlib/robust.mlw
index fbb73b12c7e3077efadf75aef7c86240b96aeed5..6a1ebe929952ae3ebe9367506dcc9fc82da46bb8 100644
--- a/stdlib/robust.mlw
+++ b/stdlib/robust.mlw
@@ -27,31 +27,31 @@
 theory ClassRobustVector
 
    use ieee_float.Float64
-   use int.Int
-   use vector.Vector
    use model.Model
+   use types.Float64WithBounds as Feature
+   use types.IntWithBounds as Label
+   use types.Vector
+   use types.VectorFloat64 as FeatureVector
 
-   type features = vector t
-   type label_ = int
-
-   predicate bounded_by_epsilon (e: features) (eps: t) =
+   predicate bounded_by_epsilon (e: FeatureVector.t) (eps: t) =
      forall i: index. valid_index e i -> .- eps .<= e[i] .<= eps
 
-   predicate advises (valid_label_: label_ -> bool)
-                     (m: model 'm) (e: features) (l: label_) =
-     valid_label_ l ->
-     forall j. valid_label_ j -> j <> l ->
+   predicate advises (label_bounds: Label.bounds) (m: model 'm)
+                     (e: FeatureVector.t) (l: Label.t) =
+     Label.valid label_bounds l ->
+     forall j. Label.valid label_bounds j -> j <> l ->
        (m @@ e)[l] .>= (m @@ e)[j]
 
-   predicate robust (valid_features: features -> bool)
-                    (valid_label_: label_ -> bool)
-                    (m: model 'm) (eps: t) (l: label_) (e: features) =
-     forall perturbed_e: vector t.
+   predicate robust (feature_bounds: Feature.bounds)
+                    (label_bounds: Label.bounds)
+                    (m: model 'm) (eps: t)
+                    (l: Label.t) (e: FeatureVector.t) =
+     forall perturbed_e: FeatureVector.t.
        has_length perturbed_e (length e) ->
-       valid_features perturbed_e ->
+       FeatureVector.valid feature_bounds perturbed_e ->
        let perturbation = perturbed_e - e in
        bounded_by_epsilon perturbation eps ->
-       advises valid_label_ m perturbed_e l
+       advises label_bounds m perturbed_e l
 
 end
 
@@ -60,14 +60,15 @@ end
 theory ClassRobustCSV
 
    use ieee_float.Float64
-   use int.Int
+   use types.Float64WithBounds as Feature
+   use types.IntWithBounds as Label
    use model.Model
    use dataset.CSV
    use ClassRobustVector
 
-   predicate robust (valid_features: features -> bool)
-                    (valid_label: label_ -> bool)
+   predicate robust (feature_bounds: Feature.bounds)
+                    (label_bounds: Label.bounds)
                     (m: model 'a) (d: dataset) (eps: t) =
-     CSV.forall_ d (ClassRobustVector.robust valid_features valid_label m eps)
+     CSV.forall_ d (ClassRobustVector.robust feature_bounds label_bounds m eps)
 
 end
diff --git a/stdlib/vector.mlw b/stdlib/types.mlw
similarity index 70%
rename from stdlib/vector.mlw
rename to stdlib/types.mlw
index 82d489d24e7412c1ca455651d80c05665768156c..7720c47ba3d1cec2b73d6b9eaa4165578aceb8e8 100644
--- a/stdlib/vector.mlw
+++ b/stdlib/types.mlw
@@ -20,7 +20,52 @@
 (*                                                                        *)
 (**************************************************************************)
 
-(** {1 Vectors} *)
+(** {1 Basic Types} *)
+
+(** {2 Generic Types with Bounds} 
+
+A generic type with bounds determining minimal and maximal value.
+
+*)
+
+theory WithBounds
+
+  type t
+  type bounds = { lower: t; upper: t }
+
+  predicate le (t1: t) (t2: t)
+
+  predicate valid (b: bounds) (t: t) =
+    le b.lower t /\ le t b.upper
+
+end
+
+(** {2 Int with Bounds} *)
+
+theory IntWithBounds
+
+  use int.Int
+
+  type t = int
+  clone export WithBounds with
+    type t = t, predicate le = (<=)
+
+end
+
+(** {2 IEEE Float64 with Bounds} *)
+
+theory Float64WithBounds
+
+  use ieee_float.Float64
+
+  type t = Float64.t
+  clone export WithBounds with
+    type t = t, predicate le = (.<=)
+
+end
+
+
+(** {1 Vector Types} *)
 
 (** {2 Generic Vectors} 
 
@@ -61,3 +106,31 @@ theory Vector
     map2 v1 v2 f
 
 end
+
+(** {2 Vectors of Int} *)
+
+theory VectorInt
+
+  use IntWithBounds
+  use Vector
+
+  type t = vector IntWithBounds.t
+
+  predicate valid (b: IntWithBounds.bounds) (v: t) =
+    Vector.forall_ v (IntWithBounds.valid b)
+
+end
+
+(** {2 Vectors of IEEE Float64} *)
+
+theory VectorFloat64
+
+  use Float64WithBounds
+  use Vector
+
+  type t = vector Float64WithBounds.t
+
+  predicate valid (b: Float64WithBounds.bounds) (v: t) =
+    Vector.forall_ v (Float64WithBounds.valid b)
+
+end
diff --git a/tests/acasxu.t b/tests/acasxu.t
index 625378a25e5715541096df1d340ea6475d30d5bc..4d4b38cdf1956f7211a954b17518de5e16546b63 100644
--- a/tests/acasxu.t
+++ b/tests/acasxu.t
@@ -7,9 +7,8 @@ Test verify on acasxu
   $ cat > file.mlw <<EOF
   > theory T
   >   use ieee_float.Float64
-  >   use bool.Bool
   >   use int.Int
-  >   use vector.Vector
+  >   use types.Vector
   >   use model.Model
   >   use model.NN
   > 
diff --git a/tests/dataset.t b/tests/dataset.t
index df6db962d3f4670a26e816042780970d5535e7c4..e14070843e20e1ecea65563101d97339ffa3ff7c 100644
--- a/tests/dataset.t
+++ b/tests/dataset.t
@@ -15,28 +15,23 @@ Test verify on dataset
   $ cat > file.mlw << EOF
   > theory T
   >   use ieee_float.Float64
-  >   use int.Int
+  >   use types.Float64WithBounds as Feature
+  >   use types.IntWithBounds as Label
   >   use model.NN
   >   use dataset.CSV
   >   use robust.ClassRobustCSV
   > 
-  >   constant min_feature_value: t = (0.0:t)
-  >   constant max_feature_value: t = (1.0:t)
+  >   constant label_bounds: Label.bounds =
+  >     Label.{ lower = 0; upper = 4 }
   > 
-  >   constant min_label: label_ = 0
-  >   constant max_label: label_ = 4
-  > 
-  >   predicate valid_features (e: features) =
-  >     CSV.valid_features min_feature_value max_feature_value e
-  > 
-  >   predicate valid_label (l: label_) =
-  >     CSV.valid_label min_label max_label l
+  >   constant feature_bounds: Feature.bounds =
+  >     Feature.{ lower = (0.0:t); upper = (1.0:t) }
   > 
   >   goal H:
   >     let nn = read_model "TestNetwork.nnet" in
   >     let dataset = read_dataset "dataset.csv" in
   >     let eps = (0.0100000000000000002081668171172168513294309377670288085937500000:t) in
-  >     robust valid_features valid_label nn dataset eps
+  >     robust feature_bounds label_bounds nn dataset eps
   > end
   > EOF
 
diff --git a/tests/goal.t b/tests/goal.t
index 7cea67f14091095a22033a7e5f5de9b4d38778e5..f95f5e184c7a80eb6d0e5af030680e2f52d9a995 100644
--- a/tests/goal.t
+++ b/tests/goal.t
@@ -7,9 +7,7 @@ Test verify
   $ cat > file.mlw <<EOF
   > theory T1
   >   use ieee_float.Float64
-  >   use bool.Bool
-  >   use int.Int
-  >   use vector.Vector
+  >   use types.Vector
   >   use model.Model
   >   use model.NN
   > 
@@ -35,9 +33,7 @@ Test verify
   > end
   > theory T2
   >   use ieee_float.Float64
-  >   use bool.Bool
-  >   use int.Int
-  >   use vector.Vector
+  >   use types.Vector
   >   use model.Model
   >   use model.NN
   > 
diff --git a/tests/marabou.t b/tests/marabou.t
index 92b2b89aa01219d720ac7e05081bfc04ab573c80..b144295313ab27e35c58a52b381dc0bbbaac1b6b 100644
--- a/tests/marabou.t
+++ b/tests/marabou.t
@@ -7,9 +7,7 @@ Test verify
   $ caisar verify --format whyml --prover=Marabou --ltag=ProverSpec - <<EOF
   > theory T
   >   use ieee_float.Float64
-  >   use bool.Bool
-  >   use int.Int
-  >   use vector.Vector
+  >   use types.Vector
   >   use model.Model
   >   use model.NN
   > 
diff --git a/tests/nier_to_onnx.t b/tests/nier_to_onnx.t
index a53221efb04d51fcfc177da81410e5a76b547740..602ca57c3a6af1f2c483d59d5a212d884e7ce1aa 100644
--- a/tests/nier_to_onnx.t
+++ b/tests/nier_to_onnx.t
@@ -7,9 +7,7 @@ Test verify
   $ caisar verify --format whyml --prover=PyRAT --ltag=NIER --onnx-out-dir="out" - 2>&1 <<EOF
   > theory NIER_to_ONNX
   >   use ieee_float.Float64
-  >   use bool.Bool
-  >   use int.Int
-  >   use vector.Vector
+  >   use types.Vector
   >   use model.Model
   >   use model.NN
   > 
diff --git a/tests/pyrat.t b/tests/pyrat.t
index 7fa35114dce7dc6cf673e426a3b4d41b3f813202..7314a569e85713fd9ea92eedec0f9f39963defda 100644
--- a/tests/pyrat.t
+++ b/tests/pyrat.t
@@ -6,11 +6,8 @@ Test verify
 
   $ caisar verify --format whyml --prover=PyRAT --ltag=ProverSpec - <<EOF
   > theory PyRAT
-  >   use TestNetwork.AsTuple
   >   use ieee_float.Float64
-  >   use bool.Bool
-  >   use int.Int
-  >   use vector.Vector
+  >   use types.Vector
   >   use model.Model
   >   use model.NN
   > 
diff --git a/tests/pyrat_onnx.t b/tests/pyrat_onnx.t
index 78d91f74a47aba6373a7b0c0ef1bb52bebc564e8..61946b96fef743f4714ee9d46e3c4ab7cff6c5d0 100644
--- a/tests/pyrat_onnx.t
+++ b/tests/pyrat_onnx.t
@@ -7,9 +7,7 @@ Test verify
   $ caisar verify --format whyml --prover=PyRAT --ltag=ProverSpec - <<EOF
   > theory PyRAT_ONNX
   >   use ieee_float.Float64
-  >   use bool.Bool
-  >   use int.Int
-  >   use vector.Vector
+  >   use types.Vector
   >   use model.Model
   >   use model.NN
   >