Converta uma Seq [String] em uma classe de caso de maneira segura
Eu escrevi um analisador que transforma uma String em uma Seq [String] seguindo algumas regras. Isso será usado em uma biblioteca.
Eu estou tentando transformar esse Seq [String] em uma classe de caso. A classe de caso seria fornecida pelo usuário (portanto, não há como adivinhar qual será).
Eu pensei em biblioteca disforme, porque parece implementar os bons recursos e parece madura, mas não tenho idéia de como proceder.
Eu encontrei esta perguntacom uma resposta interessante mas não sei como transformá-lo para minhas necessidades. De fato, na resposta há apenas um tipo para analisar (String), e a biblioteca itera dentro da própria String. Provavelmente requer uma mudança profunda na maneira como as coisas são feitas, e não tenho idéia de como.
Além disso, se possível, desejo tornar esse processo o mais fácil possível para o usuário da minha biblioteca. Portanto, se possível, diferentemente da resposta no link acima, o tipo HList seria calculado pela própria classe de caso (no entanto, de acordo com minha pesquisa, parece que o compilador precisa dessas informações).
Eu sou um pouco novo no sistema de tipos e todas essas coisas bonitas, se alguém puder me dar um conselho sobre como fazer, eu ficaria muito feliz!
Atenciosamente
--- EDIT ---
Como o ziggystar solicitou, aqui está uma possível assinatura necessária:
//Let's say we are just parsing a CSV.
@onUserSide
case class UserClass(i:Int, j:Int, s:String)
val list = Seq("1,2,toto", "3,4,titi")
// User transforms his case class to a function with something like:
val f = UserClass.curried
// The function created in 1/ is injected in the parser
val parser = new Parser(f)
// The Strings to convert to case classes are provided as an argument to the parse() method.
val finalResult:Seq[UserClass] = parser.parse(list)
// The transfomation is done in two steps inside the parse() method:
// 1/ first we have: val list = Seq("1,2,toto", "3,4,titi")
// 2/ then we have a call to internalParserImplementedSomewhereElse(list)
// val parseResult is now equal to Seq(Seq("1", "2", "toto"), Seq("3","4", "titi"))
// 3/ finally Shapeless do its magick trick and we have Seq(UserClass(1,2,"toto"), UserClass(3,4,"titi))
@insideTheLibrary
class Parser[A](function:A) {
//The internal parser takes each String provided through argument of the method and transforms each String to a Seq[String]. So the Seq[String] provided is changed to Seq[Seq[String]].
private def internalParserImplementedSomewhereElse(l:Seq[String]): Seq[Seq[String]] = {
...
}
/*
* Class A and B are both related to the case class provided by the user:
* - A is the type of the case class as a function,
* - B is the type of the original case class (can be guessed from type A).
*/
private def convert2CaseClass[B](list:Seq[String]): B {
//do something with Shapeless
//I don't know what to put inside ???
}
def parse(l:Seq[String]){
val parseResult:Seq[Seq[String]] = internalParserImplementedSomewhereElse(l:Seq[String])
val finalResult = result.map(convert2CaseClass)
finalResult // it is a Seq[CaseClassProvidedByUser]
}
}
Dentro da biblioteca, alguns implícitos estariam disponíveis para converter a String no tipo correto, conforme são adivinhados por Shapeless (semelhante à resposta proposta no link acima). Como string.toInt, string.ToDouble, e assim por diante ...
Pode haver outras maneiras de projetá-lo. É exatamente o que tenho em mente depois de jogar com Shapeless algumas horas.