替代方法
除了在您的方法中直接解决模式匹配之外,我将尝试展示一种更复杂、更通用和更实用的方法来处理这种情况。仍然模式匹配是最直接最简单的答案!
如果您可以在您的界面中明确地“证明”input
访问器,您可以概括您如何使用Something
该类。
在代码中,这转化为
trait Something[T] {
def input: T
}
case class Foo(input: Int) extends Something[Int]
case class Bar(input: Double) extends Something[Double]
从这里您可以定义如何将您喜欢的任何功能“提升”到适用于Something
s 的功能
假设您有接受两个输入(例如Ints
或Doubles
)的方法,并且您想在您的一个案例类中对这些输入进行操作(即Foo
, Bar
)
//this function lift your specific input method to one that takes Somethings
def liftSomething2[T, R](f: (T, T) => R): (Something[T], Something[T]) => R =
(a, b) => f(a.input, b.input)
让我们稍微检查一下:它接受一个
(T, T) => R
由 2 个类型参数T
和一个结果组成的函数R
并将其转换为
(Something[T], Something[T]) => R
以Something
s 作为参数的 a。
例子
//lifts a function that sums ints
scala> val sumInts = liftSomething2[Int, Int](_ + _)
sumInts: (Something[Int], Something[Int]) => Int = <function2>
//lifts a function that multiplies ints
scala> val multInts = liftSomething2[Int, Int](_ * _)
multInts: (Something[Int], Something[Int]) => Int = <function2>
//lifts a function that divides doubles
scala> val divDbl = liftSomething2[Double, Double](_ / _)
divDbl: (Something[Double], Something[Double]) => Double = <function2>
//Now some test
scala> sumInts(Foo(1), Foo(2))
res2: Int = 3
scala> multInts(Foo(4), Foo(-3))
res3: Int = -12
scala> divDbl(Bar(20.0), Bar(3.0))
res4: Double = 6.666666666666667
//You can even complicate things a bit
scala> val stringApp = liftSomething2[Int, String](_.toString + _)
stringApp: (Something[Int], Something[Int]) => String = <function2>
scala> stringApp(Foo(1), Foo(2))
res5: String = 12
上述所有示例提升类型的函数,(T,T) => R
但可以为您需要的所有和任何参数进行“提升”
//This takes three args of different types and returns another type
// the logic doesn't change
def liftSomething3[A,B,C,R](f: (A,B,C) => R): (Something[A], Something[B], Something[C]) => R =
(a,b,c) => f(a.input, b.input, c.input)
//sums to ints and divides by a double
scala> val sumDiv = liftSomething3[Int,Int,Double,Double]((i,j,d) => (i + j) / d)
sumDiv: (Something[Int], Something[Int], Something[Double]) => Double = <function3>
scala> sumDiv(Foo(5), Foo(30), Bar(4.2))
res7: Double = 8.333333333333332
更多的...
到目前为止,我们所看到的都应该与Applicative Functors和Comonads等范畴论概念有些相关,但我不是专家,所以如果你觉得这种抽象有用且有趣,我鼓励你自己搜索。