How can I use Shapeless to create a function abstracting over arity

前端 未结 2 1287
终归单人心
终归单人心 2021-02-06 08:40

Let\'s consider a specific example. I have lots of functions that take a variable number of arguments, and return a Seq[T]. Say:

def nonNeg(start: I         


        
2条回答
  •  悲哀的现实
    2021-02-06 09:29

    It is possible to use Shapeless to avoid the boilerplate—you just need to turn the original method into a FunctionN using plain old eta expansion, then convert to a function taking a single HList argument, and then back to a FunctionN with the new result type:

    import java.util.{ List => JList }
    import shapeless._, ops.function._
    import scala.collection.JavaConverters._
    
    def makeJava[F, A, L, S, R](f: F)(implicit
      ftp: FnToProduct.Aux[F, L => S],
      ev: S <:< Seq[R],
      ffp: FnFromProduct[L => JList[R]]
    ) = ffp(l => ev(ftp(f)(l)).asJava)
    

    And then:

    scala> def nonNeg(start: Int, count: Int): Seq[Int] = 
         |     Iterator.from(start).take(count).toSeq
    nonNeg: (start: Int, count: Int)Seq[Int]
    
    scala> val javaNonNeg = makeJava(nonNeg _)
    javaNonNeg: (Int, Int) => java.util.List[Int] = 
    
    scala> javaNonNeg(1, 4)
    res0: java.util.List[Int] = [1, 2, 3, 4]
    

    javaNonNeg is a Function2, so from Java you can use javaNonNeg.apply(1, 4).

提交回复
热议问题