You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将嵌套的HList of HLists结构扁平化为类型安全的单层HList

嵌套HList扁平化实现方案

可以基于Shapeless自定义递归类型类实现该需求,同时满足运行时结构转换、静态类型自动正确推导两个要求。

场景示例

运行时获取的嵌套HList实例示例:

(2 :: HNil) :: (1001 :: HNil) :: (1001 :: HNil) :: HNil

对应静态类型:

(Int :: HNil) :: (Long :: HNil) :: (Long :: HNil) :: HNil

这类嵌套HList的结构、元素类型在运行时不固定,也可能为如下形式:

(Int :: HNil) :: (String :: HNil) :: HNil

需要将其扁平化为单层HList,以上述第一个示例为例,目标输出值为:

2 :: 1001 :: 1001 :: HNil

对应目标静态类型为:

Int :: Long :: Long :: HNil

具体实现

核心思路是通过类型类递归拆解HList结构,区分头元素是否为HList做对应处理,借助Shapeless自带的Prepend完成HList拼接,自动推导最终类型:

import shapeless._

// 定义扁平化类型类,输入为嵌套HList类型IN,输出为扁平化后HList类型OUT
trait Flatten[IN <: HList, OUT <: HList] {
  def apply(input: IN): OUT
}

// 基础规则:空HList扁平化后仍为空HList
implicit val hnilFlatten: Flatten[HNil, HNil] = (input: HNil) => HNil

// 递归规则1:当前头元素本身是HList,先打平头元素、再打平尾部,最后拼接两个打平结果
implicit def hlistHeadFlatten[H <: HList, HOut <: HList, T <: HList, TOut <: HList](
  implicit
  flattenHead: Flatten[H, HOut],
  flattenTail: Flatten[T, TOut],
  prepend: Prepend[HOut, TOut]
): Flatten[H :: T, prepend.Out] = (input: H :: T) => {
  val head :: tail = input
  prepend(flattenHead(head), flattenTail(tail))
}

// 递归规则2:当前头元素是普通非HList值,将其放入结果头部,拼接打平后的尾部
implicit def plainHeadFlatten[H, T <: HList, TOut <: HList](
  implicit
  flattenTail: Flatten[T, TOut],
  prepend: Prepend[H :: HNil, TOut]
): Flatten[H :: T, prepend.Out] = (input: H :: T) => {
  val head :: tail = input
  prepend(head :: HNil, flattenTail(tail))
}

// 对外调用封装
def flatten[IN <: HList, OUT <: HList](input: IN)(implicit f: Flatten[IN, OUT]): OUT = f(input)

使用效果

直接调用flatten方法即可,编译器会自动推导扁平化后的正确静态类型:

// 测试两层嵌套示例
val nested1 = (2 :: HNil) :: (1001L :: HNil) :: (1001L :: HNil) :: HNil
val flat1 = flatten(nested1)
// flat1 静态类型为 Int :: Long :: Long :: HNil,运行时值为 2 :: 1001 :: 1001 :: HNil

// 测试不同元素类型的嵌套示例
val nested2 = (2 :: HNil) :: ("demo" :: HNil) :: HNil
val flat2 = flatten(nested2)
// flat2 静态类型为 Int :: String :: HNil,运行时值为 2 :: "demo" :: HNil

该实现不限制嵌套层级,三层及以上的嵌套HList也可以正确打平,类型推导全程由编译器完成,无运行时类型安全问题。


内容的提问来源于stack exchange,提问作者Shivam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 16:42:53