Reputation: 343
I have an HList of strings:
val strings = "The Lorax" :: "Dr. Suess" :: HNil
I another HList of special types:
case class Title(title: String, words: List[String])
case class Author(firstName: String, lastName: String)
val book = Title("The Hobbit", List("Hobbit")) :: Author("J.R.R.", "Tolkien") :: HNil
I want to turn "strings", my HList of strings, into an HList of mixed types, corresponding to the "book" list. If I have a method to go from a string -> Title, and a method to go from a string -> Author, I feel like this should be very straight forward to essentially get "strings" as an instance of "book"-list-type using shapeless, but I can't seem to figure out a way.
EDIT
My use case for this involves working on HLists that started as case classes. I'm using shapeless because I want to be able to transform and modify the data of different case classes in the same way, without having to hard-code knowledge about the shape of the case classes, I only want to have to know about the types of their values. So ideally this method would work also for going from a list of strings that looks like this:
val strings2 = "Leonardo" :: "April O'Neil" :: "The Art of Pizza" :: HNil
val book2 = Author("Michaelangelo") :: Author("Donatello") :: Title("Slicing and Dicing"), List("Slicing", "Dicing") :: HList
So I will always have an example of the format it needs to be in, but I don't want to have to hardcode the amount of "authors" and the amount of "books" into a list of translation functions. I want to be able to say "a,a,b" should look like "A, A, B", and here is a method go from "a -> A" and here is a method to go from "b -> B", but I want to be able to use the same code to go from "b, a, b" to "B, A, B", given that I have both lists.
Upvotes: 3
Views: 108
Reputation: 139028
You can do this pretty nicely with zipApply
, which applies each element of an hlist of functions to the corresponding element in another hlist:
case class Title(title: String, words: List[String])
case class Author(firstName: String, lastName: String)
// For the sake of example:
def parseTitle(s: String): Title = Title(s, s.split(' ').toList)
def parseAuthor(s: String): Author =
Author(s.takeWhile(_ != ' '), s.dropWhile(_ != ' ').tail)
import shapeless._
val funcs = parseTitle _ :: parseAuthor _ :: HNil
val strings = "The Lorax" :: "Dr. Suess" :: HNil
val book = funcs.zipApply(strings)
And then:
scala> println(book)
Title(The Lorax,List(The, Lorax)) :: Author(Dr.,Suess) :: HNil
If you need this to be more generic, you can use the ZipApply
type class instead of simply calling zipApply
on hlists with concrete types.
Upvotes: 2