gpt4 book ai didi

scala - GADT Type as Shapeless Coproduct——如何用任意数量的代数构建解释器

转载 作者:行者123 更新时间:2023-12-04 04:16:58 24 4
gpt4 key购买 nike

假设我有两种 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 类型委托(delegate)给适当的解释器。

最佳答案

你的意思是这样的?

// 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]())

关于scala - GADT Type as Shapeless Coproduct——如何用任意数量的代数构建解释器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60558145/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com