diff --git a/rr_frontend/radium/src/code.rs b/rr_frontend/radium/src/code.rs
index 140bb0e2c74e77c44f50b39952745b3bc4fc6ec3..eca6402cb5091b59f07f1aa838e872f78d595baa 100644
--- a/rr_frontend/radium/src/code.rs
+++ b/rr_frontend/radium/src/code.rs
@@ -806,13 +806,7 @@ impl<'def> Function<'def> {
         if has_params {
             write!(f, "∀ ")?;
             for param in &self.spec.coq_params {
-                // TODO use CoqParam::format instead
-                if param.implicit {
-                    write!(f, "`({})", param.ty)?;
-                } else {
-                    write!(f, "({} : {})", param.name, param.ty)?;
-                }
-                write!(f, " ")?;
+                write!(f, "{} ", param)?;
             }
 
             // assume locations for other functions
diff --git a/rr_frontend/radium/src/coq.rs b/rr_frontend/radium/src/coq.rs
index bdadb866c344dbeda9ccf331ed5ae6352600196a..95ae1c40581568381ae9c146caa4c1b0ba3c7f3c 100644
--- a/rr_frontend/radium/src/coq.rs
+++ b/rr_frontend/radium/src/coq.rs
@@ -240,13 +240,70 @@ impl CoqType {
 }
 
 #[derive(Clone, Eq, PartialEq, Debug, Display)]
-#[display("{}", display_list!(_0, " ", |(name, ty)| format!("({} : {})", name, ty)))]
-pub struct CoqParamList(pub Vec<(CoqName, CoqType)>);
+#[display("{}", self.format(true))]
+pub struct CoqParam {
+    /// the name
+    pub(crate) name: CoqName,
+
+    /// the type
+    pub(crate) ty: CoqType,
+
+    /// implicit or not?
+    pub(crate) implicit: bool,
+
+    /// does this depend on Σ?
+    pub(crate) depends_on_sigma: bool,
+}
+
+impl CoqParam {
+    #[must_use]
+    pub fn new(name: CoqName, ty: CoqType, implicit: bool) -> Self {
+        let depends_on_sigma = if let CoqType::Literal(ref lit) = ty { lit.contains('Σ') } else { false };
+
+        Self {
+            name,
+            ty,
+            implicit,
+            depends_on_sigma,
+        }
+    }
+
+    #[must_use]
+    pub fn with_name(&self, name: String) -> Self {
+        Self::new(CoqName::Named(name), self.ty.clone(), self.implicit)
+    }
+
+    #[allow(clippy::collapsible_else_if)]
+    #[must_use]
+    pub fn format(&self, make_implicits: bool) -> String {
+        if !self.implicit {
+            return format!("({} : {})", self.name, self.ty);
+        }
+
+        if make_implicits {
+            if let CoqName::Named(ref name) = self.name {
+                format!("`{{{} : !{}}}", name, self.ty)
+            } else {
+                format!("`{{!{}}}", self.ty)
+            }
+        } else {
+            if let CoqName::Named(ref name) = self.name {
+                format!("`({} : !{})", name, self.ty)
+            } else {
+                format!("`(!{})", self.ty)
+            }
+        }
+    }
+}
+
+#[derive(Clone, Eq, PartialEq, Debug, Display)]
+#[display("{}", display_list!(_0, " "))]
+pub struct CoqParamList(Vec<CoqParam>);
 
 impl CoqParamList {
     #[must_use]
-    pub const fn empty() -> Self {
-        Self(vec![])
+    pub const fn new(params: Vec<CoqParam>) -> Self {
+        Self(params)
     }
 }
 
diff --git a/rr_frontend/radium/src/specs.rs b/rr_frontend/radium/src/specs.rs
index a6415e945723323acc4a46d8d5fabd688a8386fb..fc1c15852f98173e3f442de7120614aa0024ad4f 100644
--- a/rr_frontend/radium/src/specs.rs
+++ b/rr_frontend/radium/src/specs.rs
@@ -2177,7 +2177,7 @@ impl<'def> AbstractEnum<'def> {
             let instance_decl = CoqInstanceDecl {
                 attrs: CoqAttributes::new(vec![CoqAttribute::Global]),
                 name: None,
-                params: CoqParamList::empty(),
+                params: CoqParamList::new(vec![]),
                 ty: CoqType::Literal(format!("Inhabited {}", ind.name)),
                 body: CoqDefBody::Script(
                     CoqProofScript(vec![CoqProofItem::Literal(format!("solve_inhabited"))]),
@@ -2624,63 +2624,6 @@ pub struct LoopSpec {
     pub func_predicate: IPropPredicate,
 }
 
-#[derive(Clone, Eq, PartialEq, Debug)]
-pub struct CoqParam {
-    /// the name
-    pub name: CoqName,
-    /// the type
-    pub ty: CoqType,
-    /// implicit or not?
-    pub implicit: bool,
-    /// does this depend on Σ?
-    pub depends_on_sigma: bool,
-}
-
-impl CoqParam {
-    #[must_use]
-    pub fn new(name: CoqName, ty: CoqType, implicit: bool) -> Self {
-        let depends_on_sigma = if let CoqType::Literal(ref lit) = ty { lit.contains('Σ') } else { false };
-        Self {
-            name,
-            ty,
-            implicit,
-            depends_on_sigma,
-        }
-    }
-
-    #[must_use]
-    pub fn with_name(&self, name: String) -> Self {
-        Self::new(CoqName::Named(name), self.ty.clone(), self.implicit)
-    }
-
-    #[allow(clippy::collapsible_else_if)]
-    pub fn format(&self, f: &mut Formatter, make_implicits: bool) -> fmt::Result {
-        if !self.implicit {
-            return write!(f, "({} : {})", self.name, self.ty);
-        }
-
-        if make_implicits {
-            if let CoqName::Named(ref name) = self.name {
-                write!(f, "`{{{} : !{}}}", name, self.ty)
-            } else {
-                write!(f, "`{{!{}}}", self.ty)
-            }
-        } else {
-            if let CoqName::Named(ref name) = self.name {
-                write!(f, "`({} : !{})", name, self.ty)
-            } else {
-                write!(f, "`(!{})", self.ty)
-            }
-        }
-    }
-}
-
-impl Display for CoqParam {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        self.format(f, true)
-    }
-}
-
 /**
  * A Caesium function specification.
  */
diff --git a/rr_frontend/translation/src/type_translator.rs b/rr_frontend/translation/src/type_translator.rs
index 18b002b14be3d6702bfecc0d62441b6dd5ca8b46..749e86c5ef6cd4070109095418a59b61893ce097 100644
--- a/rr_frontend/translation/src/type_translator.rs
+++ b/rr_frontend/translation/src/type_translator.rs
@@ -1100,13 +1100,18 @@ impl<'def, 'tcx: 'def> TypeTranslator<'def, 'tcx> {
             let (variant_args, variant_arg_binders, variant_rfn) = if variant_def.fields.is_empty() {
                 (vec![], vec![], "-[]".to_string())
             } else {
-                let args = vec![(radium::CoqName::Unnamed, radium::CoqType::Literal(refinement_type))];
+                let args = vec![radium::CoqParam::new(
+                    radium::CoqName::Unnamed,
+                    radium::CoqType::Literal(refinement_type),
+                    false,
+                )];
+
                 (args, vec!["x".to_string()], "x".to_string())
             };
 
             let variant_def = radium::CoqVariant {
                 name: variant_name.to_string(),
-                params: radium::CoqParamList(variant_args),
+                params: radium::CoqParamList::new(variant_args),
             };
 
             variants.push(variant_def);
@@ -1116,7 +1121,7 @@ impl<'def, 'tcx: 'def> TypeTranslator<'def, 'tcx> {
         // We assume the generated Inductive def is placed in a context where the generic types are in scope.
         let inductive = radium::CoqInductive {
             name: enum_name.to_string(),
-            parameters: radium::CoqParamList(vec![]),
+            parameters: radium::CoqParamList::new(vec![]),
             variants,
         };