简体   繁体   English

斯卡拉下界类型“与”另一种类型?

[英]scala lower bound type “with” another type?

Here is the code 这是代码

class Result[A] {
    def map[B](f: (Result[A] => Result[B]), xResult: Result[A]) = {
      xResult match {
        case Success(x)    => Success(f(xResult))
        case Failure(errs) => Failure(errs)
      }
    }

    def apply[B](fResult: Result[A], xResult: Result[B]) = {
      (fResult, xResult) match {
        case (Success(f), Success(x))        => Success((f, x))
        case (Failure(errs), Success(a))     => Failure(errs)
        case (Success(a), Failure(errs))     => Failure(errs)
        case (Failure(errs), Failure(errs2)) => Failure(List(errs, errs2))
      }
    }
  }

  case class Success[A](a: A) extends Result[A] {}

  case class Failure[A](a: A) extends Result[A] {}

  def createCustomerId(id: Int) = {
    if (id > 0)
      Success(id)
    else
      Failure("CustomerId must be positive")
  }

Here are the questions 这是问题

1) result from type inference from method createCustomer is like this 1)从方法createCustomer的类型推断得出的结果是这样的

Product with Serializable with Result[_ >: Int with String] 

I dont have trouble with the "Product with Serializable" stuff, the thing im wondering is how to do something meaningfull with the result, and just out of curiosity how to initialize a type like that. 我对“带有可序列化的产品”的东西没有任何疑问,我想知道的是如何对结果进行有意义的处理,而出于好奇,如何初始化这样的类型。

suppose i have another method as shown below 假设我有另一种方法,如下所示

def createCustomer(customerId: Result[_ >: Int with String], email: Result[String]) = {
    how can i read/do something with "customerId" argument
  }

how to initialize a type like that 如何初始化这样的类型

val x: Result[Int with String] = ???

notes: 笔记:

  1. i know my Result class doesnt have any generic "getter" 我知道我的Result类没有任何通用的“ getter”
  2. I know that perhaps things could be easier in method "createCustomerId" if when id > 0 i returned Success(id.ToString), but i really want to know whats going on with this lower type and how i could take advantage (if possible) in the future 我知道,如果id> 0时返回“ Success(id.ToString)”,也许方法“ createCustomerId”中的事情可能会更容易,但是我真的很想知道这种较低类型的情况以及如何利用(如果可能)在将来

The problem is that your type definition states that both Success and Failure take the same argument type. 问题是您的类型定义指出SuccessFailure采用相同的参数类型。 However, you actually want to put some other type of argument into Failure while still keeping covariance. 但是,您实际上想将其他类型的参数放入“ Failure同时仍然保持协方差。 Here is the simplest fix: 这是最简单的解决方法:

class Result[A] {

  def map[B](f: (Result[A] => Result[B]), xResult: Result[A]) = {
    xResult match {
      case Success(x) => Success(f(xResult))
      case Failure(errs) => Failure(errs)
    }
  }

  def apply[B](fResult: Result[A], xResult: Result[B]) = {
    (fResult, xResult) match {
      case (Success(f), Success(x)) => Success((f, x))
      case (Failure(errs), Success(a)) => Failure(errs)
      case (Success(a), Failure(errs)) => Failure(errs)
      case (Failure(errs), Failure(errs2)) => Failure(List(errs, errs2))
    }
  }
}

case class Success[A](a: A) extends Result[A] {}

case class Failure[A, B](a: B) extends Result[A] {}

object TestResult extends App {

  def createCustomerId(id: Int): Result[Int] = {
    if (id > 0)
      Success(id)
    else
      Failure("CustomerId must be positive")
  }

  println(createCustomerId(0))
  println(createCustomerId(1))
}

prints: 印刷品:

Failure(CustomerId must be positive)
Success(1)

If you don't annotate return type for createCustomerId with Result[Int] compiler will infer Result[_ <: Int] with Product with Serializable which is probably not ideal but not too bad. 如果您不使用Result[Int]注释createCustomerId返回类型,则编译器将Result[_ <: Int] with Product with Serializable来推断Result[_ <: Int] with Product with Serializable这可能不理想,但也不太差。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM