将无形的可扩展记录传递给函数 [英] Passing a Shapeless Extensible Record to a Function

查看:46
本文介绍了将无形的可扩展记录传递给函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习 Shapeless(使用 2.10.2 版).我创建了一个非常简单的可扩展记录:

I am trying to learn Shapeless (using version 2.10.2). I have created a very simple extensible record:

val rec1 = ("foo" ->> 42) :: HNil

根据 REPL,这有类型

According to the REPL, this has type

shapeless.::[Int with shapeless.record.KeyTag[String("foo"),Int],shapeless.HNil]

我正在尝试定义一个简单的函数:

I am trying to define a simple function:

def fun(x: ::[Int with KeyTag[String("foo"), Int], HNil]) = x("foo")

但它甚至无法编译.我不能在类型声明中使用 String("foo") 并得到一个错误.

but it does not even compile. I cannot use a String("foo") in the type declaration, and get an error.

我有两个问题:

  1. 如何在代码中指定可扩展记录的类型?
  2. 处理具有更多字段的记录时,类型声明的长度和复杂性将难以管理.有没有办法为该类型创建别名(给定记录的特定实例)或其他一些解决方法?

编辑

我发现:

val rec1 = ("foo" ->> 42) :: HNil
val rec2 = ("foo" ->> 43) :: HNil
var x = rec1
x = rec2

效果很好.我得出的结论是 rec1、rec2 和 x 属于同一类型.我只是不知道如何在代码中表达这种类型!

works well. I conclude rec1, rec2, and x are of the same type. I just don't know how to express that type in code!

推荐答案

这里有一些更笼统的东西,我认为可以回答您的问题.假设我们要编写一个方法,该方法可以处理带有 "foo" 键的任何记录.我们可以结合使用见证和选择器:

Here's something a little more general that I think might answer your question. Suppose we want to write a method that will work on any record with a "foo" key. We can use a combination of a witness and a selector:

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")

然后:

scala> fun(("foo" ->> 42) :: HNil)
res0: Int = 42

或者:

scala> fun(("bar" ->> 'a) :: ("foo" ->> 42) :: HNil)
res1: Int = 42

如果我们真的只想允许没有其他字段的记录,我们可以这样写:

If we really wanted to only allow records with no other fields, we could write the following:

def fun(l: Int with KeyTag[w.T, Int] :: HNil) = l("foo")

但这与通常使用记录的方式有些矛盾.

But that's somewhat at odds with the way records are generally used.

我们必须精确地定义见证,因为 Scala 2.10 没有提供任何直接引用单例类型的方法——例如参见 my fork Alois Cochard 的 Shona 项目进行了一些讨论.

We have to define the witness precisely because Scala 2.10 doesn't provide any way to refer to a singleton type directly—see for example my fork of Alois Cochard's Shona project for some discussion.

作为最后的免责声明,我要补充一点,我自己才刚刚熟悉 Shapeless 2.0,但我认为即使是 Miles 也没有足够的魔力来解决这个限制.

I will add as a final disclaimer that I'm only just now getting familiar with Shapeless 2.0 myself, but I don't think even Miles is magical enough to get around this limitation.

这篇关于将无形的可扩展记录传递给函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆