【问题标题】:Funny observation about (recursive) structural types in Scala关于 Scala 中(递归)结构类型的有趣观察
【发布时间】:2026-01-10 19:40:01
【问题描述】:

我需要在一些代码中使用带有特征的递归结构类型,并将结构类型用作类型参数约束。它工作得很好,但后来我了解到 Scala 不支持递归结构类型。

那么有人可以解释一下为什么这样可以正常工作:

scala> trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {}
defined trait Test

这不是:

scala> def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null
<console>:5: error: illegal cyclic reference involving type M
       def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null

【问题讨论】:

    标签: scala structural-typing


    【解决方案1】:

    我认为这是编译器中的一个小故障。以下代码表现出与您的初始代码相同的行为:

    trait Test[M[A] <: { def map: M[A] } ] {}
    def test[M[A] <: { def map: M[A] } ] = null
    

    它会导致编译时错误:“非法循环引用”。

    以下代码没有(即编译良好):

    type S[M] = { def map: M }
    
    trait Test[M[A] <: S[M[A]] ] {}
    def test[M[A] <: S[M[A]] ] = null
    

    唯一的区别是结构类型在这里通过类型别名 S 应用。

    【讨论】:

    • 实际上我喜欢使用类型别名的解决方案,它甚至适用于函数定义。但是您的第一个示例的行为与我的完全一样,说 Test-trait 编译得很好。但如果它使用类型别名工作,它肯定也应该不使用它们工作?!?
    • 是的,我认为这里有一些不一致之处:它应该与类型别名一起工作而没有,或者根本不应该工作。这就是为什么我认为这是编译器中的一个小故障。
    • 您有错误跟踪编号吗?
    【解决方案2】:

    第一个代码 sn-p 在 Scala 2.7.7final 中也抛出错误:

    scala> trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {}
    <console>:4: error: illegal cyclic reference involving type M
           trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {}
                                                        ^
    

    您使用哪个版本的 Scala?

    【讨论】:

      最近更新 更多