St.
St.

Reputation: 533

HList as parameter of method with simplified type signature

Suppose I have container-marker

case class TypedString[T](value: String)

where value represents some id for particular type T.

I have two classes

case class User(id: String)
case class Event(id: String)

And I have a function which does some stuff:

def func[L <: HList](l: L)(...) {...}

So I can use it like

func[TypedString[User] :: TypedString[Event] :: HNil](
    TypedString[User]("user id") :: TypedString[Event]("event id") :: HNil
)

(it's important for me to keep type signature explicitly)

The question is: how to change or extends func to have shorter type signature (keeping only marker types) like:

func[User :: Event :: HNil](
    TypedString[User]("user id") :: TypedString[Event]("event id") :: HNil
)

Upvotes: 4

Views: 180

Answers (1)

Peter Neyens
Peter Neyens

Reputation: 9820

The shapeless.ops.hlist.Mapped type class gives you the relation of one HList L and another HList where the elements of L are wrapped in a type constructor.

Because you have now two types, the type L you want to specify and another type (the elements of L wrapped in TypedString), we need to use the same trick we used in your previous question (then because we didn't want to supply all the arguments at once, now because we only want to specify the first type).

import shapeless._
import ops.hlist.Mapped

def func[L <: HList] = new PartFunc[L]

class PartFunc[L <: HList] {
  def apply[M <: HList](m: M)(implicit mapped: Mapped.Aux[L, TypedString, M]): M = m
}

Now you can use func as you wanted :

func[User :: Event :: HNil](
    TypedString[User]("user id") :: TypedString[Event]("event id") :: HNil
)
// TypedString[User] :: TypedString[Event] :: HNil =
//     TypedString(user id) :: TypedString(event id) :: HNil

Upvotes: 2

Related Questions