[英]Scala shapeless polymorphic value function for numeric types
I need to write a function that will receive a function that will transform a List[T]
into a T
. 我需要编写一个函数来接收一个将List[T]
转换为T
的函数。 For example, summing the elements of the list. 例如,总结列表的元素。
My first try was to use shapeless polymorphic functions as: 我的第一次尝试是使用无形多态函数:
object sumPoly extends (List ~> Option) = {
def apply[T: Numeric](list: List[T]): Option = Some(list.sum)
}
but I get an error because shapeless expect the function to be def apply[T](...)
但我得到一个错误,因为无形期望函数是def apply[T](...)
The function that receives the function above would look like: 接收上述函数的函数如下所示:
def test(list: List[Any], f: (List ~> Option)) = {
val intTypeCase = TypeCase[List[Int]]
val doubleTypeCase = TypeCase[List[Double]]
val longTypeCase = TypeCase[List[Long]]
list match {
intTypeCase(l) => f(l)
doubleTypeCase(l) => f(l)
longTypeCase(l) => f(l)
// more type matchings here
}
...
}
Is there a way to achieve what I want to do? 有没有办法实现我想做的事情?
After some searches I found that it is possible to do the following: 经过一些搜索后,我发现可以执行以下操作:
object sumPoly extends Poly1 {
implicit def caseListInt = at[List[Int]](x => x.sum)
implicit def caseListDouble = at[List[Double]](x => x.sum)
// more type matchings here
}
and calling sumPoly(List(1, 1, 1))
correctly returns 3
. 并且调用sumPoly(List(1, 1, 1))
正确返回3
。 But if I define the test
function as: 但是,如果我将test
函数定义为:
def test(list: List[Any], f: Poly1) = {
val intTypeCase = TypeCase[List[Int]]
val doubleTypeCase = TypeCase[List[Double]]
val longTypeCase = TypeCase[List[Long]]
list match {
intTypeCase(l) => f(l)
doubleTypeCase(l) => f(l)
longTypeCase(l) => f(l)
// more type matchings here
}
...
}
and pass the sumPoly
function, I get the errors like this for each type I defined in the test
function: could not find implicit value for parameter cse: shapeless.poly.Case[f.type,shapeless.::[List[Int],shapeless.HNil]]
并传递sumPoly
函数,我为test
函数中定义的每个类型得到这样的错误: could not find implicit value for parameter cse: shapeless.poly.Case[f.type,shapeless.::[List[Int],shapeless.HNil]]
Any ideas? 有任何想法吗?
By looking at shapeless' code I found I can do the following: 通过查看无形的代码,我发现我可以执行以下操作:
object sumPoly extends Poly1 {
implicit def caseList[T: Numeric] = at[List[T]] { x => x.sum }
}
and then the function which will receive the Poly1
must have the following definition: 然后接收Poly1
的函数必须具有以下定义:
def test(list: List[Any], f: Poly1)
(implicit li : f.Case[List[Int]],
ld : f.Case[List[Double]],
ll : f.Case[List[Long]])= {
val intTypeCase = TypeCase[List[Int]]
val doubleTypeCase = TypeCase[List[Double]]
val longTypeCase = TypeCase[List[Long]]
list match {
intTypeCase(l) => f(l)
doubleTypeCase(l) => f(l)
longTypeCase(l) => f(l)
// more type matchings here
}
...
}
this way, I can create different Poly1
functions like sum
, prod
, min
, max
that convert List[T]
into a T
where T
is numeric. 这样,我可以创建不同的Poly1
函数,如sum
, prod
, min
, max
,将List[T]
转换为T
,其中T
是数字。
The design might seem contrived, but I am interop-ing with Java. 设计可能看似人为,但我正在与Java交互。 More specifically, with Hadoop libraries written in Java. 更具体地说,使用Java编写的Hadoop库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.