Skip to main content

abstract class

abstract class KvpHList[H<:HList]
  object KvpNil extends KvpHList[HNil]
  case class KvpCons[H <: A :: T,A, T<:HList](head: KvpValue[A], tail: KvpHList[T])(implicit isHCons: IsHCons.Aux[H,A,T]) extends KvpHList[H] {
    val hCons: IsHCons.Aux[H,A,T] = isHCons
  }

  abstract class KvpValue[A]
  case object StringData extends KvpValue[String]
  case class HListData[H <:HList](member: KvpHList[H]) extends KvpValue[H]

  def hListInterpreter[H<:HList](hList: KvpHList[H]): H => String = {
      hList match {
        case KvpNil => (hNil: H) => "Nil"
        case cons: KvpCons[H,a,t]=> {
          implicit val hCons = cons.hCons
          (input: H) => {
            s"${kvpInterpreter(cons.head)(input.head)} :: ${hListInterpreter(cons.tail)(input.tail)}"
          }
        }
      }
  }

  def kvpInterpreter[A](kvpValue: KvpValue[A]): A => String = {
    kvpValue match {
      case StringData => (str: String) => str
      case h: HListData[h] => {
        (input: A) => {                               // tried (input: h) as well
          val toString: h => String = hListInterpreter(h.member)
          toString(input.asInstanceOf[h])             // <--- CASTING :(
        }
      }
    }
  }

  kvpInterpreter(HListData(KvpCons(StringData, KvpNil))).apply("Hello" :: HNil)