Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Scala中编写一个可以处理多个参数类型的服务?_Scala_Types_Typeclass_Type Systems_Type Level Computation - Fatal编程技术网

如何在Scala中编写一个可以处理多个参数类型的服务?

如何在Scala中编写一个可以处理多个参数类型的服务?,scala,types,typeclass,type-systems,type-level-computation,Scala,Types,Typeclass,Type Systems,Type Level Computation,我正在设计一个API。基本上是这样的: trait Service { def performUseCase[T](transferObjects: Iterable[TransferObject[T]]) } trait TransferObject[T] { def data: T } case class TransferObjectA[T](data: T) extends TransferObject[T] case class TransferObject

我正在设计一个API。基本上是这样的:

trait Service {

    def performUseCase[T](transferObjects: Iterable[TransferObject[T]])

}

trait TransferObject[T] {

    def data: T

}

case class TransferObjectA[T](data: T) extends TransferObject[T]
case class TransferObjectB[T](data: T) extends TransferObject[T]
注意:如有必要,我可以更改
TransferObject
s的实现。语义上重要的是:

  • 至少有两种
    TransferObject
    s
  • 传输对象必须以任何方式建立顺序。现在,如何构建顺序并不那么重要:一个
    Seq[TransferObject[\u]
    ,或者一个传输对象引用下一个或多个对象
  • 将有不同的
    服务
    特性实现。对于每个
    服务
    实例,必须指定此实例可以处理的类型。

    示例:此服务
    val myService=myService()
    可以处理
    TransferObjects[MyTypeA]
    TransferObjects[MyTypeB]
    等。当API用户试图传递
    TransferObjects[MyUnknownType]
    时,编译器应抛出错误

    我读过Scala的类型系统,类型类(比如隐式)和类型声明,但我还不了解所有细节

    我尝试使用
    服务
    特性的实现,将特定于类型的处理程序作为类型类。
    MyHandler[MyTypeA]
    MyHandler[MyTypeB]
    等,并使用implicits为当前参数类型传入正确的处理程序。但是处理程序不应向API用户公开。这就是为什么我想知道,如果用户传入
    服务
    无法处理的类型的参数,是否可能引发编译器错误

    真正的实现更复杂,而且目前还不完善。也许我可以稍后再交付一些代码


    综述:

    同样:我需要多个服务实例。每个实例都应该能够处理多个参数类型。如果传入未知类型的参数,编译器应该抛出一个错误。特定类型的处理程序被视为实现细节,应该对API用户保持隐藏


    我如何认识到这一点?

    您可以使用
    密封的trait TransferObject[T]{…
    案例类TransferObjectA(数据:Int)扩展TransferObject[Int]…
    def performUseCase[T](transferObjects:Iterable[TransferObject[T]])
    的内部

    transferObject match{
    case TransferObjectA(myInt) => ...
    ...
    }//throws warning because of unmatched TransferObjectB on compile time because of sealed trait
    

    还可以查看您可以使用
    密封的trait TransferObject[T]{…
    案例类TransferObjectA(数据:Int)扩展TransferObject[Int]…
    def performUseCase[T](transferObjects:Iterable[TransferObject[T]])
    的内部

    transferObject match{
    case TransferObjectA(myInt) => ...
    ...
    }//throws warning because of unmatched TransferObjectB on compile time because of sealed trait
    

    还可以看看

    这里有一个基于类型类的方法:

    trait TransferObject[T] {
      def data: T
    }
    
    case class TransferObjectA[T](data: T) extends TransferObject[T]
    case class TransferObjectB[T](data: T) extends TransferObject[T]
    
    trait Service {
      protected[this] trait Handler[A] {
        def apply(objs: Iterable[TransferObject[A]]): Unit
      }
    
      def performUseCase[A](objs: Iterable[TransferObject[A]])(
        implicit handler: Handler[A]
      ) = handler(objs)
    }
    
    然后:

    object MyIntAndStringService extends Service {
      implicit object intHandler extends Handler[Int] {
        def apply(objs: Iterable[TransferObject[Int]]) {
          objs.foreach(obj => printf("Int: %d\n", obj.data))
        }
      }
    
      implicit object stringHandler extends Handler[String] {
        def apply(objs: Iterable[TransferObject[String]]) {
          objs.foreach(obj => printf("String: %s\n", obj.data))
        }
      }
    }
    
    val ints = List(1, 2, 3).map(TransferObjectA(_))
    val strings = List("A", "B", "C").map(TransferObjectA(_))
    val chars = List('a', 'b', 'c').map(TransferObjectA(_))
    
    最后:

    scala> MyIntAndStringService.performUseCase(ints)
    Int: 1
    Int: 2
    Int: 3
    
    scala> MyIntAndStringService.performUseCase(strings)
    String: A
    String: B
    String: C
    
    scala> MyIntAndStringService.performUseCase(chars)
    <console>:14: error: could not find implicit value for parameter handler: MyIntAndStringService.Handler[Char]
                  MyIntAndStringService.performUseCase(chars)
                                                      ^
    
    scala>MyIntAndStringService.performUseCase(ints)
    内部:1
    内部:2
    内部:3
    scala>MyIntAndStringService.performUseCase(字符串)
    字符串:A
    字符串:B
    字符串:C
    scala>MyIntAndStringService.performUseCase(chars)
    :14:错误:找不到参数处理程序MyIntAndStringService.handler[Char]的隐式值
    MyIntAndStringService.performUseCase(chars)
    ^
    

    根据需要。

    这里有一种基于类型类的方法:

    trait TransferObject[T] {
      def data: T
    }
    
    case class TransferObjectA[T](data: T) extends TransferObject[T]
    case class TransferObjectB[T](data: T) extends TransferObject[T]
    
    trait Service {
      protected[this] trait Handler[A] {
        def apply(objs: Iterable[TransferObject[A]]): Unit
      }
    
      def performUseCase[A](objs: Iterable[TransferObject[A]])(
        implicit handler: Handler[A]
      ) = handler(objs)
    }
    
    然后:

    object MyIntAndStringService extends Service {
      implicit object intHandler extends Handler[Int] {
        def apply(objs: Iterable[TransferObject[Int]]) {
          objs.foreach(obj => printf("Int: %d\n", obj.data))
        }
      }
    
      implicit object stringHandler extends Handler[String] {
        def apply(objs: Iterable[TransferObject[String]]) {
          objs.foreach(obj => printf("String: %s\n", obj.data))
        }
      }
    }
    
    val ints = List(1, 2, 3).map(TransferObjectA(_))
    val strings = List("A", "B", "C").map(TransferObjectA(_))
    val chars = List('a', 'b', 'c').map(TransferObjectA(_))
    
    最后:

    scala> MyIntAndStringService.performUseCase(ints)
    Int: 1
    Int: 2
    Int: 3
    
    scala> MyIntAndStringService.performUseCase(strings)
    String: A
    String: B
    String: C
    
    scala> MyIntAndStringService.performUseCase(chars)
    <console>:14: error: could not find implicit value for parameter handler: MyIntAndStringService.Handler[Char]
                  MyIntAndStringService.performUseCase(chars)
                                                      ^
    
    scala>MyIntAndStringService.performUseCase(ints)
    内部:1
    内部:2
    内部:3
    scala>MyIntAndStringService.performUseCase(字符串)
    字符串:A
    字符串:B
    字符串:C
    scala>MyIntAndStringService.performUseCase(chars)
    :14:错误:找不到参数处理程序MyIntAndStringService.handler[Char]的隐式值
    MyIntAndStringService.performUseCase(chars)
    ^
    
    如所愿