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

Scala 3中元组类型工作原理:为何无法匹配HList形式类型?

Scala 3元组与HList类型匹配失败的原因

问题背景

有人告知Scala 3的元组表现类似Scala 2中shapeless的HList,因此进行了如下简单实验:

val tuple = (1, "String", 1.1)

val _: *:[Int, *:[String, Double]] = tuple // 无法通过编译
val _: *:[Double, *:[String, Int]] = tuple // 无法通过编译

根据HList的定义,上述两种类型匹配中至少有一种应该可行,但实际均失败,完整报错信息如下:

[Error] /home/peng/git/dottyspike/src/main/scala/com/tribbloids/spike/dotty/NewTuple.scala:15:42: Found:    (tuple : (Int, String, Double))
Required: Int *: String *: Double

Explanation
===========

Tree: tuple
I tried to show that
  (tuple : (Int, String, Double))
conforms to
  Int *: String *: Double
but none of the attempts shown below succeeded:

  ==> (tuple : (Int, String, Double))  <:  Int *: String *: Double class dotty.tools.dotc.core.Types$CachedTermRef class dotty.tools.dotc.core.Types$CachedAppliedType
    ==> (Int, String, Double)  <:  Int *: String *: Double class dotty.tools.dotc.core.Types$CachedAppliedType class dotty.tools.dotc.core.Types$CachedAppliedType
      ==> (String, Double)  <:  String *: Double class dotty.tools.dotc.core.Types$CachedAppliedType class dotty.tools.dotc.core.Types$CachedAppliedType
        ==> Double *: EmptyTuple.type  <:  Double class dotty.tools.dotc.core.Types$CachedAppliedType class dotty.tools.dotc.core.Types$CachedTypeRef  = false

The tests were made under the empty constraint

[Error] /home/peng/git/dottyspike/src/main/scala/com/tribbloids/spike/dotty/NewTuple.scala:17:42: Found:    (tuple : (Int, String, Double))
Required: Double *: String *: Int

Explanation
===========

Tree: tuple
I tried to show that
  (tuple : (Int, String, Double))
conforms to
  Double *: String *: Int
but none of the attempts shown below succeeded:

  ==> (tuple : (Int, String, Double))  <:  Double *: String *: Int class dotty.tools.dotc.core.Types$CachedTermRef class dotty.tools.dotc.core.Types$CachedAppliedType
    ==> (Int, String, Double)  <:  Double *: String *: Int class dotty.tools.dotc.core.Types$CachedAppliedType class dotty.tools.dotc.core.Types$CachedAppliedType
      ==> Int  <:  Double class dotty.tools.dotc.core.Types$CachedTypeRef class dotty.tools.dotc.core.Types$CachedTypeRef  = false

The tests were made under the empty constraint

two errors found

原因解析

1. 类型结构不完整

Scala 3的元组确实基于*:(Cons运算符)和EmptyTuple构建,(A, B, C)的等价底层类型是A *: B *: C *: EmptyTuple。但你写的*:[Int, *:[String, Double]]等价于Int *: String *: Double,缺少了末尾的*: EmptyTuple,和元组的完整类型不匹配,这是第一个匹配失败的核心原因。

2. 类型顺序严格匹配

第二个匹配尝试Double *: String *: Int是元组类型的完全反转,不管是Scala 3元组还是shapeless HList,都是严格有序的异构列表,元素类型的顺序是类型的一部分。(Int, String, Double)对应的HList类型只能是Int *: String *: Double *: EmptyTuple,反转后的类型和原类型完全不兼容,自然无法通过编译。

3. 正确的写法示例

如果要让类型匹配通过,需要写出完整的HList风格类型,或者直接使用元组的标准类型:

// 完整HList风格类型匹配
val _: Int *: String *: Double *: EmptyTuple = tuple // 编译通过
// 标准元组类型匹配
val _: (Int, String, Double) = tuple // 编译通过

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 06:37:35