是否有无样板的方法将HLists转换为参数列表?

时间:2014-11-19 22:11:16

标签: scala macros spray shapeless hlist

根据this question Spray使用sbt-boilerplate生成ApplyConverter个实例,这些实例隐式地将A :: B :: ... :: HNil => R转换为更传统的(A, B, ...) => R以便于使用。这个问题是在一年前提出来的;现在可以使用宏或Shapeless的新功能来完成这个,这样就不需要外部代码生成步骤吗?

2 个答案:

答案 0 :(得分:3)

很长一段时间以来,它一直被包括在内。在无形2.0.0中,您可以执行以下操作,

scala> import shapeless._, syntax.std.function._
import shapeless._
import syntax.std.function._

scala> val f1: (Int, String, Boolean) => Int = (i, s, b) => i+s.length+(if(b) 1 else 0)
f1: (Int, String, Boolean) => Int = <function3>

scala> val pf1 = f1.toProduct
pf1: Int :: String :: Boolean :: HNil => Int = <function1>

scala> pf1(23 :: "foo" :: true :: HNil)
res0: Int = 27

scala> val pf2: (Int :: String :: HNil) => Int = l => l.head+l.tail.head.length
pf2: Int :: String :: HNil => Int = <function1>

scala> val f2 = pf2.fromProduct
f2: (Int, String) => Int = <function2>

scala> f2(23, "foo")
res1: Int = 26

(为了便于阅读,整理了REPL结果类型)。

答案 1 :(得分:0)

我认为在纯Scala中无法做到这一点,因为没有办法一般性地谈论FunctionN接口。在宏观层面,它是可能的,但不是以使用AST表示形式的方式;执行此操作的宏可能会减少(有效地)进行字符串操作 - 在这种情况下,与sbt-boilerplate相比,它没有什么优势。

即使它确实成为可能,Spray也是一个相当基础的库,需要与其他库一起使用(因此它继续针对旧版本的Scala和Akka构建版本) - 这一点只会变得更加重要当Play被移植到Spray之上时。所以我希望在Spray引入对Shapeless 2(与Shapeless 1不兼容)的硬依赖之前会有一段时间,直到那时我想他们会尝试保持无形2喷涂路由的代码尽可能接近尽可能为shapeless1构建,以便于维护。