我正在尝试学习Shapeless(使用版本2.10.2).我创建了一个非常简单的可扩展记录:
val rec1 = ("foo" ->> 42) :: HNil
根据REPL,这有类型
shapeless.::[Int with shapeless.record.KeyTag[String("foo"),Int],shapeless.HNil]
我试图定义一个简单的函数:
def fun(x: ::[Int with KeyTag[String("foo"), Int], HNil]) = x("foo")
Run Code Online (Sandbox Code Playgroud)
但它甚至没有编译.我不能在类型声明中使用String("foo"),并得到错误.
我有两个问题:
编辑
我发现:
val rec1 = ("foo" ->> 42) :: HNil
val rec2 = ("foo" ->> 43) :: HNil
var x = rec1
x = rec2
Run Code Online (Sandbox Code Playgroud)
效果很好.我得出结论rec1,rec2和x属于同一类型.我只是不知道如何在代码中表达该类型!
Tra*_*own 26
这里有一些更普遍的东西,我认为可能会回答你的问题.假设我们想要编写一个可以使用"foo"密钥处理任何记录的方法.我们可以使用见证和选择器的组合:
import shapeless._, record._, syntax.singleton._
val w = Witness("foo")
def fun[L <: HList](xs: L)(implicit sel: ops.record.Selector[L, w.T]) = xs("foo")
Run Code Online (Sandbox Code Playgroud)
然后:
scala> fun(("foo" ->> 42) :: HNil)
res0: Int = 42
Run Code Online (Sandbox Code Playgroud)
要么:
scala> fun(("bar" ->> 'a) :: ("foo" ->> 42) :: HNil)
res1: Int = 42
Run Code Online (Sandbox Code Playgroud)
如果我们真的只想允许没有其他字段的记录,我们可以编写以下内容:
def fun(l: Int with KeyTag[w.T, Int] :: HNil) = l("foo")
Run Code Online (Sandbox Code Playgroud)
但这与通常使用记录的方式有些不一致.
我们必须准确定义见证,因为Scala 2.10没有提供任何直接引用单例类型的方法 - 例如参见我的Alois Cochard的Shona项目的分支进行讨论.
我将添加最后的免责声明,我现在才刚刚熟悉Shapeless 2.0,但我不认为即使是Miles也足以克服这个限制.
从无形2.1.0开始,有一种表达记录类型的新语法:
scala> :paste
// Entering paste mode (ctrl-D to finish)
import shapeless._
import shapeless.record._
import shapeless.syntax.singleton._
def fun(x: Record.`"foo" -> Int`.T) = x("foo")
// Exiting paste mode, now interpreting.
import shapeless._
import shapeless.record._
import shapeless.syntax.singleton._
fun: (x: shapeless.::[Int with shapeless.labelled.KeyTag[String("foo"),Int],shapeless.HNil])Int
scala> fun( ("foo" ->> 42) :: HNil )
res2: Int = 42
scala> fun( ("foo" ->> 42) :: ("bar" ->> 43) :: HNil )
<console>:30: error: type mismatch;
found : shapeless.::[Int with shapeless.labelled.KeyTag[String("foo"),Int],shapeless.::[Int with shapeless.labelled.KeyTag[String("bar"),Int],shapeless.HNil]]
required: shapeless.::[Int with shapeless.labelled.KeyTag[String("foo"),Int],shapeless.HNil]
fun( ("foo" ->> 42) :: ("bar" ->> 43) :: HNil )
Run Code Online (Sandbox Code Playgroud)
但选择器可能是OP用例的最佳方法.