3

Given a function f, that, given a Map[String, MyType], returns a HList:

package net

import shapeless._

sealed trait MyType
case object MyInt extends MyType
case object MyStr extends MyType

object Mapper {

    def f(m: Map[String, MyType]): HList = m.foldLeft[HList](HNil){ (acc, elem) =>
        val (key, t) = elem
        t match {
            case MyInt => classOf[Int] :: acc
            case MyStr => classOf[String] :: acc
        } 
    }
}

I tested it:

import net._
val list = Map("foo" -> MyInt, "bar" -> MyStr)

scala> Mapper.f(list)
res0: shapeless.HList = class java.lang.String :: int :: HNil

How can I use the above approach (or another one) to build a case class with members matching the String keys, and the types given by the output of f?

So, I'm looking for:

g(Map("foo" -> MyInt, "bar" -> MyStr)) to output case class X(foo: Int, bar: String) where X is arbitrarily chosen, i.e. not important at this point.

I thought of using Generic[X], but I don't know how to get a Generic without a case class first.

Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384
  • Possible duplicate: http://stackoverflow.com/questions/20684572/scala-convert-map-to-case-class – Alfredo Gimenez Sep 16 '16 at 19:57
  • I don't believe it's a dupe since I am trying to produce a case class. The other answer already provides one, as I see it. – Kevin Meredith Sep 16 '16 at 19:58
  • Ah I see, hm using a `String` to create a variable name could possibly require some advanced reflection, I can imagine a macro function could do it, but others may be able to point you to a third-party solution. I may take a stab at the macro solution if nothing else comes up. – Alfredo Gimenez Sep 16 '16 at 20:06
  • 99.9% of the time `HList` is useless as a static type. You could have something like a function taking a map (optionally) into an extensible record, but you'd still need to specify the record type statically. – Travis Brown Sep 20 '16 at 12:20

1 Answers1

2

The thing you're trying to do can't happen in Scala with compile time verification. The issue here is exactly as you've elaborated, you don't have the definition of the case class you're trying to build in advance. That definition provides the scaffolding to use a Record type to construct the isomorphism.

That said, we might be able to work something with invoke dynamic and reflection but I'm unclear on how you'd even take advantage of that in code. You wouldn't know the field names in advance nor their types. So how would you even write code around them?

wheaties
  • 35,646
  • 15
  • 94
  • 131