В соответствии с этим вопросом Spray использует sbt-boilerplate для создания ApplyConverter
экземпляров, которые неявно преобразуют A :: B :: ... :: HNil => R
в более традиционный (A, B, ...) => R
для простоты использования. . Этот вопрос был задан более года назад; можно ли теперь это сделать, используя, например, макросы или новую функциональность Shapeless, чтобы не требовался этап генерации внешнего кода?
Есть ли способ без шаблонов преобразовать HLists в список аргументов?
Ответы (2)
Это было включено в бесформенное в течение очень долгого времени. В shapeless 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 приведено в порядок для удобочитаемости).
Я думаю, что в чистом Scala это сделать невозможно, так как нет возможности в общем говорить об интерфейсах FunctionN
. На макроуровне это было бы возможно, но не так, чтобы можно было использовать представление AST; макрос для этого, вероятно, будет сведен к (эффективному) выполнению манипуляций со строками - в этом случае очень мало преимуществ перед sbt-boilerplate.
Даже если бы это стало возможным, Spray — довольно фундаментальная библиотека, которую необходимо использовать в сочетании с другими библиотеками (таким образом, она продолжает создавать выпуски для старых версий Scala и Akka) — что-то, что станет более важным только тогда, когда Play портирован для работы поверх Spray. Так что я ожидаю, что пройдет какое-то время, прежде чем Spray введет жесткую зависимость от Shapeless 2 (которая несовместима с Shapeless 1), и до тех пор, я думаю, они попытаются сохранить код для shapeless2 сборки spray-routing как можно ближе. насколько это возможно для бесформенной1 сборки для простоты обслуживания.
FunctionN
. Таким образом, макрос должен будет использовать манипуляции со строками, чтобы получить правильный FunctionN
. Дело не в том, что макрос не может этого сделать, а в том, что макрос не может сделать это лучше, чем текстовый процессор.
- person lmm; 20.11.2014
FunctionN
интерфейсами в макросе. Есть элемент AST для анонимной функции, где вам просто нужно передать нужное количество параметров. Тем не менее, я думаю, что понимаю, о чем вы говорите: на каком-то уровне вам нужно сделать какой-то тупой перевод (и лучше сделать это прямо в компиляторе).
- person jrudolph; 20.11.2014
FunctionN
. Насколько я могу судить, shapeless по-прежнему генерирует свои экземпляры FnFromProduct, используя шаблон. - person Jonathan Chow   schedule 21.11.2014