Scala 具有上下文绑定的任何类型

Scala 具有上下文绑定的任何类型,scala,Scala,免责声明:我不确定我是否真的理解类型上下文边界。。。或者别的什么 是否可以在scala中定义一个类型,该类型是TypeClass的实例,该类型可以是任意类型,只要该类型遵守类型上下文绑定 例如,我有一些typeclassPrintable[T] Printable是一个typeclass,用于可以打印的内容,它作为类型上下文绑定非常有用,因为我可能希望typeclass可以接受任何类型,只要它是可打印的,如下所示: class SomeContainer[T: Printable](value:

免责声明:我不确定我是否真的理解类型上下文边界。。。或者别的什么

是否可以在scala中定义一个类型,该类型是TypeClass的实例,该类型可以是任意类型,只要该类型遵守类型上下文绑定

例如,我有一些typeclass
Printable[T]

Printable是一个typeclass,用于可以打印的内容,它作为类型上下文绑定非常有用,因为我可能希望typeclass可以接受任何类型,只要它是可打印的,如下所示:

class SomeContainer[T: Printable](value: T)
据我所知,集合库对可以排序、求和等的内容使用了这样的类型上下文边界

但是我想要的是
键入PrintableAnyCollection=SomeCollection[\uux:Printable]

这是一个可以是不同类型的值的集合,只要所有这些类型都服从类型上下文绑定,那么该类型就存在一个
Printable[T]

TLDR:

Collection[Any]
几乎满足了我的需求,因为它可以容纳不同的类型

Collection[T:Printable]
几乎满足了我的要求,因为它强制要求集合中的内容是可打印的,但其结果是集合只存储一种类型


Collection[\uu:Printable]
和/或
Collection[Any:Printable]
看起来好像它们描述了我想要的东西,但不是有效的语法。

你大概在寻找这样的东西:

// Doesn't work
Collection[T forSome {type T: Printable}]
但这不起作用,原因是上下文边界只是隐式参数的糖,隐式参数在编译时解析。特别是,上面的类型意味着编译器的隐式解析取决于上面类型的运行时值(每个不同的
T
都需要另一个隐式解析)。实际上,您将创建一个方法,其隐式参数列表中的arity在运行时可能会更改

我只想说这对Scala不好

另一种方法是将隐式参数主动绑定到某种包装器类型中,并将包装器上的集合参数化为存在参数。因此,隐式解析在创建集合之前发生。迈尔斯·萨宾(Miles Sabin)很好地涵盖了这一点

简要总结一下这种方法,如下所示:

case class PrintableWrapper[T](unwrap: T)(implicit ev: Printable[T])

Collection[PrintableWrapper[T] forSome {type T}]
实际上,使用集合的条目很麻烦(为了安抚Scala的typechecker,需要一个虚假的模式匹配)。desugared上下文绑定还需要有一个Printable的显式实例来实际打印条目。有关更多详细信息,请参阅迈尔斯·萨宾的答案


这恰好是隐式编码是一种稍微麻烦的类型类编码方式。

这个答案最终让我问了更多的问题,但最终给了我一个可接受的解决方案。您链接到的另一个线程是关于Scala中异构列表的上下文边界这一更大问题的讨论。最终我解决了问题,放弃了类型类,使用了子类型,这非常不雅观,因为我正在与之交互的库使用类型类,因此我需要一堆填隙片,但将类型类与case类和继承一起使用完全耗尽了我的复杂性预算。