HList形状类型扩展共同特征

4

我有一些基于shapeless HLists的类型:

type t1 = Int :: String :: Int :: HNil
type t2 = String :: String :: Int :: HNil

我希望定义一个密封特质ST,它是所有类型的超类型,这样,如果我有以下函数:

def fun(x:ST) = …

以下是有效的:
fun(5 :: "foo" :: 3 :: HNil)       // It is a t1
fun("foo" :: "bar" :: 42 :: HNil)  // It is a t2

但以下代码无法编译:

fun(5 :: 3 :: HNil)

我该如何定义t1t2作为ST的子类型? 更新 我认为余积可能是一个解决方案。
type ST = t1 :+: t2 :+: CNil

fun(Coproduct[ST](5 :: "foo" :: 3 :: HNil)) // compiles
fun(Coproduct[ST](5 :: 3 :: HNil))          // does not compile
1个回答

3

使用别名是不可能将一个类型变成任何子类型的,因为别名只是一个新名称。虽然您可以使用余积,但创建一个新的类型类可能更自然:

import shapeless._

type t1 = Int :: String :: Int :: HNil
type t2 = String :: String :: Int :: HNil

trait Funnable[A]

implicit object t1Funnable extends Funnable[t1]
implicit object t2Funnable extends Funnable[t2]

def fun[A: Funnable](x: A) = x

现在,您想编译的行将被编译,而您不想编译的行则不会。


谢谢!我将其改编为:def fun[A <: HList](x:A)(implicit funnable:Funnable[A]) = x,以保留 x 的一些类型信息。 - Eduardo
太好了!请注意,您还可以在类型类本身的类型参数上添加HList约束(这取决于您如何使用它是否有意义)。 - Travis Brown
事实上,这是我尝试的第一件事,但编译器(Scala 2.10.??)无法推断函数参数x是HList。最终,我保留了两个约束条件。 - Eduardo
1
抱歉我表达不够清楚,但是是的,我的意思是你可以在两个地方都加入约束条件。 - Travis Brown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接