Michael
Michael

Reputation: 42100

How to invoke function of multiple arguments with HList?

Suppose I have an HList of type A::B::C::HNil and a function (A, B, C) => D

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

Now I need a funciton A::B::C::HNil => D, which uses foo to return D.

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

How would you implement bar ?

Upvotes: 5

Views: 416

Answers (2)

Travis Brown
Travis Brown

Reputation: 139058

You can do this a little more directly using Shapeless's FnToProduct, which provides toProduct syntax for converting a FunctionN into a Function1 taking an 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)

In many cases you probably wouldn't even want a separate bar definition.

Upvotes: 10

Peter Neyens
Peter Neyens

Reputation: 9820

You can use the Shapeless conversion from HList to Tuple, and use Function.tupled with your original function :

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

Upvotes: 2

Related Questions