如何用HList调用多参数函数?

How to invoke function of multiple arguments with HList?

假设我有一个 HList 类型 A::B::C::HNil 和一个函数 (A, B, C) => D

val hlist: A::B::C::HNil = ???
def foo(a: A, b: B, c: C): D = ???

现在我需要一个函数 A::B::C::HNil => D,它使用 foo 到 return D.

def bar(hslist: A::B::C::HNil): D = ???

您将如何实施 bar

您可以使用从 HListTuple 的无形转换,并将 Function.tupled 与您的原始函数一起使用:

def sum(a: Int, b: Int) = a + b

def sumHList(hlist: Int :: Int :: HNil) = {
  val tupledSum = Function.tupled(sum _)
  tupledSum(hlist.tupled)
}

def sumHList2(hlist: Int :: Int :: HNil) = hlist.head + hlist.tail.head

sum(1, 2)
sumHList(1 :: 2 :: HNil)
sumHList2(1 :: 2 :: HNil)
// result from all three = 3

您可以使用 Shapeless 的 FnToProduct 更直接地完成此操作,它提供了 toProduct 语法,用于将 FunctionN 转换为 Function1,采用 HList:

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

type A = String
type B = Symbol
type C = Int
type D = List[String]

val hlist: A :: B :: C :: HNil = "foo" :: 'x :: 1 :: HNil

def foo(a: A, b: B, c: C): D = List.fill(c)(a + b)

def bar(hslist: A :: B :: C :: HNil): D = (foo _).toProduct.apply(hslist)

在许多情况下,您可能甚至不需要单独的 bar 定义。