简体   繁体   English

Scala无形多态值函数用于数值类型

[英]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? 有没有办法实现我想做的事情?

EDIT 编辑

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函数,如sumprodminmax ,将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.

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