scala - 如何在 Scala 的类型类中使用依赖类型?
问题描述
我想为几个不同的-s定义一对类型(A
和B
in )。例如,for = (在隐式对象中定义)。然后我想在类型类定义中使用这些类型级别的依赖关系。 trait Dep[C]
C
A=String
B=View
C
View1
DepInstanceView1
如何定义一个类型类实例(此处ServerSideFun[View1]
),该实例具有具有依赖输入和返回类型(此处定义于 中DepInstanceView1
)的函数?
换句话说,我想要一个类型级别的函数,它来自C -> (A,B)
(此处定义了一个此类类型级别映射)并在类型类声明(此处)及其实例(此处)中DepInstanceView1
使用此类型级别函数。trait ServerSideFun[C]
View1Conv
有人可以建议一种方法吗?
或者如何修改下面的代码来编码这种类型级别,类型依赖的约束f
(正如它所暗示的那样trait ServerSideFun[C]
)在类型类中?
我这样做的尝试以编译器错误告终:
source_file.scala:47: error: type mismatch;
found : Int(42)
required: B
def f[A, B] (a:A)(implicit aux:Dep.Aux[View1,A,B]):B = 42
^
one error found
代码示例:
下面的代码可以在这里在线执行:http ://rextester.com/GYWW78561
object Rextester extends App {
println("Hello, World!3")
}
trait Dep[C]{
type A
type B
}
trait View1
trait View2
object Dep{
type Aux[C0, A0, B0]= Dep[C0] {type A=A0; type B= B0}
implicit object DepInstanceView1 extends Dep[View1] {
type A=String
type B=Int
}
}
trait ServerSideFun[C]
{
def f[A,B] (a:A)(implicit aux:Dep.Aux[C,A,B]):B
}
object ServerSideFun {
implicit object View1Conv extends ServerSideFun[View1]{
def f[A, B] (a:A)(implicit aux:Dep.Aux[View1,A,B]):B = 42
}
}
编辑 :
我更新了代码以阐明意图:http ://rextester.com/YVBV30174
这是:
1)定义几个View
-s :
trait View1
trait View2
2) 为每个View
-s 定义一个单独的类型级别映射View -> (A,B)
,例如:
View1-> (String,Int)
在DepInstanceView1
View2-> (String,String)
在DepInstanceView2
3) 可以有几种不同的类型类实现ServerSideFun
,例如:
- 一进
object ServerSideFun
- 另一个在
object ServerSideFunAlternativeImplementation
.
本质上:
- 类型类的所有实例
ServerSideFun[C]
都应遵循.View -> (A,B)
object Dep
f
因此,对于给定的函数,函数的每个定义(实现)View
都必须采用类型的输入参数A
并返回类型的结果B
。
这是代码:
object Rextester extends App {
println("Hello, World!3")
}
trait Dep[C]{
type A
type B
}
trait View1
trait View2
object Dep{
type Aux[C0, A0, B0]= Dep[C0] {type A=A0; type B= B0}
implicit object DepInstanceView1 extends Dep[View1] {
type A=String
type B=Int
}
implicit object DepInstanceView2 extends Dep[View2] {
type A=String
type B=String
}
}
trait ServerSideFun[C]
{
def f[A,B] (a:A)(implicit aux:Dep.Aux[C,A,B]):B
}
object ServerSideFun {
implicit object View1Conv extends ServerSideFun[View1]{
def f[A, B] (a:A)(implicit aux:Dep.Aux[View1,A,B]):B = 42
}
implicit object View2Conv extends ServerSideFun[View2]{
def f[A, B] (a:A)(implicit aux:Dep.Aux[View2,A,B]):B = "42"
}
}
object ServerSideFunAlternativeImplementation {
implicit object View1Conv extends ServerSideFun[View1]{
def f[A, B] (a:A)(implicit aux:Dep.Aux[View1,A,B]):B = 43
}
implicit object View2Conv extends ServerSideFun[View2]{
def f[A, B] (a:A)(implicit aux:Dep.Aux[View2,A,B]):B = "43"
}
}
解决方案
如果ServerSideFun[C]
应该包含f: A => B
某些类型的函数的实现A
and B
,那么ServerSideFun[C]
显然必须知道类型A
和B
是什么,否则它将必须f
从来自 trait 之外的某些部分组成函数ServerSideFun[C]
。但是我们可以包含type A
和type B
,ServerSideFun[C]
然后完全放弃Dep[C]
:
trait View1
trait View2
trait ServerSideFun[C]{
type A
type B
def f(a: A): B
}
object ServerSideFun {
implicit object View1Conv extends ServerSideFun[View1] {
type A = String
type B = Int
def f(a: String): Int = 42
}
}
如果你愿意,你可以重新引入,Dep[C]
然后扩展Dep[C]
:ServerSideFun[C]
trait Dep[C]{
type A
type B
}
trait View1
trait View2
object Dep {
trait DepInstanceView1 extends Dep[View1] {
type A = String
type B = Int
}
}
trait ServerSideFun[C] extends Dep[C] {
def f(a: A): B
}
object ServerSideFun {
implicit object View1Conv
extends ServerSideFun[View1]
with Dep.DepInstanceView1 {
def f(a: String): Int = 42
}
}
如果不是完全通用函数的某种“自然组合”,那么在某些时候你将不得不在已知的上下文中写下f
它的主体。在体内写下混凝土,但同时将完全未指定的内容从外部引入是行不通的。f
A
B
42
A
B
Dep.Aux[View1,A,B]
推荐阅读
- react-native - 滑动手势不会在 React-Navigation 中打开/关闭抽屉
- android - 如何在反应原生屏幕之间传递数据?
- jboss - Wildfly 模块线程安全
- python - 如何使用 Python 连接到 Tor 浏览器
- c - 使用 cryptoauthlib 配置 ATEC608A
- robotframework - RIDE 的 Robotframework 运行问题
- c# - 无法在 Windows 10 版本的 NavigationView 的项目模板中实现相同的行为
- java - 为什么Java需要cmd /c或者cmd /k来执行多段adb
- css - 产品页面woocomerce上的文件图标不会消失
- python-3.x - 如何使用python将xml标签转换为字典?