GADT类型为无形副产品-如何构建具有任意数量的代数的解释器

特拉维斯·史蒂文斯(Travis Stevens)

假设我有两种GADT类型。

  abstract class Numbers[A]()
  case class IntType() extends Numbers[Int]

  abstract class Letters[A]()
  case class EnglishType() extends Letters[String]

我为每种GADT类型都有一个解释器,它将为每种GADT子类型打印出说明。

  trait Interpreter[ALG[_],A] {
    def description(a: ALG[A]) : String
  }

  case class NumbersInterpreter[A]() extends Interpreter[Numbers,A] {
    override def description(a: Numbers[A]): String =
      a match {
        case i: IntType => "Int"
      }
  }

  case class LettersInterpreter[A]() extends Interpreter[Letters,A] {
    override def description(a: Letters[A]): String =
      a match {
        case e: EnglishType => "English"
      }
  }

我希望将两个GADT合并为一个名为All的GADT

  type All[A] = Numbers[A] :+: Letters[A] :+: CNil

我可以通过对所有GADT值进行硬编码来创建新的解释器。

  case class DualInterpreter[A](
    numbersInterpreter: NumbersInterpreter[A],
    lettersInterpreter: LettersInterpreter[A]) extends Interpreter[All,A] {
    override def description(a: All[A]): String =
      a match {
        case Inl(num) => numbersInterpreter.description(num)
        case Inr(Inl(let)) => lettersInterpreter.description(let)
        case _ => sys.error("Unreachable Code")
      }
  }

但是,我想添加一堆GADT代数和解释器,然后将它们任意组合为一个代数,因此我正在寻找一种更通用的方法来替代DualInterpreter上述内容。我可以看到类型签名类似于

  case class ArbitraryInterpreter[ALG[_]<:Coproduct,A](???) extends Interpreter[ALG,A] {
    override def description(a: ALG[A]): String = ???
  }

我要抽象的最主要的是description方法内部的模式匹配,因为随着可用代数的增加,它可能变得很丑陋。它将有一个解释器,其中构造函数参数是解释器,并且基于传递到描述方法中的ALG类型,将模式匹配的委托委派给适当的解释器。

马特乌斯·库布佐克(Mateusz Kubuszok)

你的意思是这样吗?

// using kind projector
def merge[L[_], R[_] <: Coproduct, A](
  li: Interpreter[L, A],
  ri: Interpreter[R, A]
): Interpreter[Lambda[A => L[A] :+: R[A]] , A] =
  new Interpreter[Lambda[A => L[A] :+: R[A]] , A] {
    override def description(lr: L[A] :+: R[A]): String =
      lr match {
        case Inl(l) => li.description(l)
        case Inr(r) => ri.description(r)
      }
  }

也许与

implicit class InterpreterOps[L[_], A](val l: Interpreter[L, A]) extends AnyVal {

  def ++ [R[_] <: Coproduct](r: Interpreter[R, A]): Interpreter[Lambda[A => L[A] :+: R[A]] , A] = merge(l, r)
}

用作


type CNilF[A] = CNil // trick to make things consistent on kind-level
case class CNilInterpreter[A]() extends Interpreter[CNilF, A] {
  override def description(a: CNilF[A]): String = ???
}

def allInterpreter[A]: Interpreter[All, A] =
  // :+: is right associative, but normal methods are left associative,
  // so we have to use parens
  NumbersInterpreter[A]() ++ (LettersInterpreter[A]() ++ CNilInterpreter[A]())

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何提取缩小的类型并将其用于Shapeless的副产品中?

无形-副产品中的重复数据删除类型

无形的:从副产品映射到不同的副产品

Functor产品和副产品的有用应用

展开/剥离无形副产品对象

无形中的副产品无法编译

无礼的副产品子类型

带有副产品和monad变压器的Scala Free Monads

坐姿中的产品和副产品

扩展副产品的自然转化

如何使用无形来迭代联产品中的所有产品类型?

如何使用无形为具有依赖类型的类型类创建实例

副产品优于“密封性状”的好处?

我的副产品编码不明确

Haskell副产品和数据记录字段限制

如何上传任意数量的具有不同文件类型的文件

如何检查无形类型是否为HList的成员?

如何为具有任意数量的 Any 类型关键字参数的 Callable 类型定义 Python 协议?

如何获取json中每个对象的级别,其中对象可以具有任意数量的相同对象类型的子对象

Scala使用无定形在自然转化中结合更高种类的副产品

使用 Jackson 属性累积状态作为序列化的副产品

在Haskell中,如何根据GADT将无类型的AST解析为有类型的AST?

订单条目具有多个销售数量的产品,如何根据销售数量获得最畅销的产品

如何动态执行具有任意参数类型的函数指针?

如何区分具有不同幻像类型的GADT构造函数?

如何创建具有可变数量的类型参数的模板?

运行中具有类型类要求的无形HList foldLeft

无形:遍历联产品中的类型

如何构建具有属性的强类型XML POST请求