如何在 Scala 中的类型 类 中使用依赖类型?

How to use dependent types inside type classes in Scala?

我想为几个不同的 C -s 定义一对类型(Atrait Dep[C] 中的 B )。例如,A=StringB=View 代表 C=View1(在隐式对象 DepInstanceView1 中定义)。然后我想在 type class 定义中使用这些类型级别的依赖关系。

如何定义类型 class 实例(此处 ServerSideFun[View1]),它具有依赖输入的函数和 return 类型(此处在 DepInstanceView1 中定义)?

换句话说,我想要一个从 C -> (A,B) 开始的类型级函数(这里在 DepInstanceView1 中定义了一个这样的类型级映射)并在输入 class 声明(此处 trait ServerSideFun[C])及其实例(此处 View1Conv)。

有人可以建议一种方法吗?

或者如何修改下面的代码以编码这种类型级别的方法,在类型 class 中对 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 :

2) 为每个 View-s 定义一个单独的类型级别映射 View -> (A,B),例如:

3) 使得 class ServerSideFun 类型的多个不同实现成为可能,例如:

本质上 :

代码如下:

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] 应该包含某些类型 AB 的函数 f: A => B 的实现,那么 ServerSideFun[C] 显然必须知道AB 是什么类型,否则它必须从特征 ServerSideFun[C] 之外的一些部分组成函数 f。但是我们可以将 type Atype 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 不是一些 "natural composition" 完全通用的函数,那么在某些时候你将不得不在 [=14= 的上下文中写下 f 的主体] 和 B 是已知的。在正文中写下一个具体的42,但同时从外部将完全未指定的AB引入Dep.Aux[View1,A,B]是行不通的。