Как использовать зависимые типы внутри классов типов в Scala? - PullRequest
0 голосов
/ 19 мая 2018

Я хотел бы определить пару типов (A и B в 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]) в классе типов?

Myпопытка сделать это закончилась ошибкой компилятора:

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 определяют отдельное отображение уровня типаView -> (A,B), например:

  • View1-> (String,Int) в DepInstanceView1
  • View2-> (String,String) в DepInstanceView2

3) сделать возможнымиметь несколько различных реализаций класса типа ServerSideFun, например:

  • одна в object ServerSideFun
  • другая в object ServerSideFunAlternativeImplementation.

По существу :

  • все экземплярыpe class 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"
  }

}

1 Ответ

0 голосов
/ 19 мая 2018

Если ServerSideFun[C] должен содержать реализацию функции f: A => B для некоторых типов A и B, то ServerSideFun[C], очевидно, должен знать, что такое типы A и B,в противном случае пришлось бы составлять функцию f из некоторых фрагментов, которые поступают извне черты 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] извне не работает.

...