我希望定义一个函数,它接受两个类型为Any的args并尝试添加它们,如下所示:
def plus(x:Any,y:Any):Try[Any] = {
...
}
如果操作数是可以添加的类型(算术,不是字符串连接或类似的东西),则产生成功,如果不是,则返回Failure。例如:
val x:Any = 1
val y:Any = 2
val z = plus(x,y) // z = Success(3)
或
val x:Any = "wrong"
val y:Any = 2
val z = plus(x,y) // z = Failure(...)
并且,我希望通过添加来进行类型提升工作:Int + Int => Int,Int + Double =>双,等等。
我知道必须有一个聪明而简洁的方法来做到这一点,而不必检查匹配的每种可能的类型组合。我对Scala很新(只有一周),所以我会很感激任何建议。
答案 0 :(得分:1)
在您的示例中,您知道编译时的参数类型。在这种情况下,您可以使用类型系统做得更好:
scala> def plus[T: Numeric](a: T, b: T) = implicitly[Numeric[T]].plus(a, b)
plus: [T](a: T, b: T)(implicit evidence$1: Numeric[T])T
scala> plus(1, 2)
res0: Int = 3
scala> plus(1, 2.5)
res1: Double = 3.5
scala> plus(1, "2")
<console>:9: error: could not find implicit value for evidence parameter of type Numeric[Any]
plus(1, "2")
^
答案 1 :(得分:0)
已更新:哎呀!我错过了你问题的最后一部分。如果您尝试添加两种不同的类型,例如Int + Double => Double
,我所解释的并不起作用。
我认为你可以使用Scalaz的Monoid
简单地说,它看起来像这样
trait Monoid[F] extends Semigroup[F] {
def zero: F
def append(f1: F, f2: => F): F
}
因此,如果您想使用它,您需要做的就是导入Scalaz
import scalaz._
import Scalaz._
然后你可以简单地做
1 |+| 1 // result: 2
"a" |+| "b" // result: ab
BigInt(100) |+| BigInt(100) // BigInt(200)
Scalaz为大多数已知类型(如Int,BigInt,BigDecimal,String等)提供隐式类型转换,但如果您有自己的类型并且想要使其可附加,则可以轻松完成。
我们假设您有类似
的类型case class Something(value: Int)
您可以使用隐式类型转换,例如。
implicit def SomethingMonoid = new Monoid[Something] {
override def zero: Something = Something(0)
override def append(f1: Something, f2: => Something): Something = Something(f1.value |+| f2.value) // you can even use |+| here as value is Int
}
现在,你可以做到
Something(10) |+| Something(100) // result: Something(110)
如果要重复使用它,只需使用Scalaz导入SomethingMonoid
import scalaz._
import Scalaz._
import your.package.SomethingMonoid
// Or
import scalaz._
import Scalaz._
// ...
val somethingMonoid = your.package.SomethingMonoid
然后你可以做
Something(111) |+| Something(222) // result: Something(333)
使用Monoid来处理结果比使用方法更好并返回Try [T]因为你没有得到编译时类型安全性而Monoid会给你一个编译时错误,如果你做的话,< / p>
Something(10) |+| 100 // a compile-time error
如果你真的想拥有自己的加号,你可以做这样的事情
def plus[T](x: T, y: T)(implicit monoid: Monoid[T]): Try[T] = Try(monoid.append(x, y))
正如我上面解释的那样使用Scalaz,但是当类型不匹配时你会得到一个编译时错误,所以没有必要使用Try除非计算可能会引发一些异常。
plus(1, 2) // result: 3
plus(Something(1), Something(9)) // result: Something(10)
plus("one", 2) // result: a compile-time error