首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在GADT中使用HList时,我必须使用asInstanceOf[H]进行转换。有没有办法避免演员阵容?

在GADT中使用HList时,我必须使用asInstanceOf[H]进行转换。有没有办法避免演员阵容?
EN

Stack Overflow用户
提问于 2019-05-29 22:03:40
回答 1查看 87关注 0票数 3

给定两个相互了解的GADT代数和两个相互递归的解释器,我遇到了从类型A转换为类型h <:HList的问题,尽管在模式匹配的上下文中,应该暗示类型A是类型h。

有没有办法避免解释器中的asInstanceOf[h]调用?

代码语言:javascript
复制
  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)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-30 01:12:04

由于KvpCons中的HAT唯一确定,因此可以使用两个类型参数而不是三个类型参数来参数化KvpCons

类型级模式匹配是类型类

代码语言:javascript
复制
  abstract class KvpHList[H <: HList]
  object KvpNil extends KvpHList[HNil]
  case class KvpCons[A, T <: HList](head: KvpValue[A], tail: KvpHList[T]) extends KvpHList[A :: T]

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

  trait HListInterpreter[H <: HList] {
    def apply(hList: KvpHList[H]): H => String
  }

  object HListInterpreter {
    implicit val nil: HListInterpreter[HNil] = new HListInterpreter[HNil] {
      override def apply(hList: KvpHList[HNil]): HNil => String = _ => "Nil"
    }

    implicit def cons[A, T <: HList](implicit
                                     headKvpInterpreter: KvpInterpreter[A],
                                     tailHListInterpreter: HListInterpreter[T]
                                    ): HListInterpreter[A :: T] = new HListInterpreter[A :: T] {
      override def apply(hList: KvpHList[A :: T]): A :: T => String = hList match {
        case cons: KvpCons[_, _] => input => s"${headKvpInterpreter(cons.head)(input.head)} :: ${tailHListInterpreter(cons.tail)(input.tail)}"
      }
    }
  }

  def hListInterpreter[H <: HList](hList: KvpHList[H])(implicit hListInterp: HListInterpreter[H]): H => String = hListInterp(hList)

  trait KvpInterpreter[A] {
    def apply(kvpValue: KvpValue[A]): A => String
  }

  object KvpInterpreter {
    implicit val string: KvpInterpreter[String] = new KvpInterpreter[String] {
      override def apply(kvpValue: KvpValue[String]): String => String = str => str
    }

    implicit def hList[H <: HList : HListInterpreter]: KvpInterpreter[H] = new KvpInterpreter[H] {
      override def apply(kvpValue: KvpValue[H]): H => String = kvpValue match {
        case h: HListData[H] => input => {
          val toString: H => String = hListInterpreter(h.member)
          toString(input)
        }
      }
    }
  }

  def kvpInterpreter[A](kvpValue: KvpValue[A])(a: A)(implicit kvpInterp: KvpInterpreter[A]): String = kvpInterp(kvpValue)(a)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56362440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档