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

如何为Int实现Intf trait,将指定FooBar[Int]作为given成员?

Scala中如何复用已有类型类实例实现特质的given成员?

在Scala中,我们定义了类型类trait FooBar[X],并且已经存在一个全局的given intIsFoobar: FooBar[Int]实例。另外有一个特质Intf,它包含成员类型A,同时要求在该特质内部存在一个given FooBar[A]实例。

在尝试为Int实现Intf时遇到了几个问题:

  • 直接用summon实现会触发**"IntImpl.aIsFoobar函数体无限循环"**错误,因为summon会优先引用当前正在定义的aIsFoobar,而非全局的intIsFoobar;
  • 用私有辅助变量存储summon结果会出现初始化顺序问题,导致aIsFoobar为null并触发空指针异常;
  • 尝试使用export语法无法通过编译。

我们需要解决的问题是:如何将全局标准的FooBar[Int]实例作为IntImpl中的aIsFoobar这个given成员?

问题代码

trait FooBar[X]

given intIsFoobar: FooBar[Int] = new FooBar {}

trait Intf:
  type A
  given aIsFoobar: FooBar[A]

object IntImpl extends Intf:
  type A = Int
  given aIsFoobar: FooBar[A] = summon

可行解决方案

方案1:显式引用全局given实例

直接在实现中明确指定全局的intIsFoobar实例,完全避免summon的歧义问题:

object IntImpl extends Intf:
  type A = Int
  given aIsFoobar: FooBar[A] = intIsFoobar

这种方式最直接,适合全局实例有明确名称的场景。

方案2:限定summon的具体类型

通过显式指定summon的目标类型,跳过当前正在定义的aIsFoobar,直接查找全局的FooBar[Int]实例:

object IntImpl extends Intf:
  type A = Int
  given aIsFoobar: FooBar[A] = summon[FooBar[Int]]

这里不再依赖类型推导的FooBar[A],而是明确指定查找FooBar[Int],编译器会直接匹配全局的intIsFoobar。

方案3:使用using从句引入外部实例

通过using从句显式引入外部的FooBar[Int]实例,再赋值给aIsFoobar:

object IntImpl extends Intf:
  type A = Int
  given aIsFoobar: FooBar[A] = (using fb: FooBar[Int]) => fb

这种写法更灵活,适合需要依赖外部上下文提供实例的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:17:21