如何处理高阶类型的元组?

问题描述 投票:0回答:1

Scala 3,显然。 Scala 2 的

Tuple
设置会阻止我尝试这个。

我正在尝试编写一个带有可插入算法的通用解析器库。所以,当你写你的语法时,它会被转换成一个抽象语法树,然后这些抽象语法树被提供给你想要使用的任何算法,算法决定它如何解析输入。

所以,例如,我有这些数据类都扩展了

ParseExpr[+T]

case class Term[T](t: T) extends ParseExpr[T] // a single terminal
case class NonTerm[T](name: String) extends ParseExpr[T] // a non-terminal
      // I also store the type of the non-terminal, but it's ugly

case class Alt[T](ps: List[Pexpr[T]]) extends ParseExpr[T] // a list of alternate ParseExprs
case class Cat[?](ps: ?) extends ParseExpr[?] // a sequence of ParseExprs

除最后一个外,一切正常。 Scala 解析器组合器处理等效的

Alt
Cat
的方式是将它们二值化。换句话说,您只能在
ParseExpr
Alt
中有两个
Cat
,但它们也可以是
Alt
Cat
,因此您可以用
p ~ q ~ r
构建
Cat(Cat(p, q), r)
的等价物.

我正在实现一种算法,当解析器没有二值化时,它的速度要快得多,所以我正在尝试创建一个

Cat
的版本,它需要任意数量的
ParseExpr
s。当然,问题是一系列解析器的结果是一个(异构的)值序列。所以我想我可以使事情完全通用并使用新的 Scala 3
Tuple
.

这是我尝试过的:

case class Cat[Ts <: Tuple](ps: Map[Ts, ParseExpr]) extends ParseExpr[Ts]

我认为这说明的是

Cat
采用一个
ParseExpr
的元组,每个元组都有自己的类型,并按顺序生成给定类型的元组。这很棒。除了我不能用它做任何事。

首先,我必须将

Cat[Ts](pes: Map[Ts, ParseExpr])
转换为实际的解析器。为此,我必须将每个
ParseExpr
转换为
Parser
。所以我试着
map
超过
Tuple

parseExpr match
  case Cat(ps) => ps.map([t] => (pe: t) => parserFor(pe)) // should return Map[Ps, Parser]

但是无论我怎么做,我都无法进行类型检查。

我是不是贪多嚼不烂,

Tuple
高阶类型的麻烦多于它们的价值,还是我在这里遗漏了一些基本的东西?

scala tuples scala-3 higher-order-types
1个回答
1
投票

如果你开始使用 HLists aka Tuples 执行类型级计算(像

Tuple.Map
这样的元组操作是根据匹配类型定义的)你应该继续使用

  • 匹配类型,或

  • 类型类。

您应该准备好使用匹配类型(尤其是在值级别)可能会很棘手,有很多限制,并且类型推断非常薄弱

如何在 Scala 3 中证明 `Tuple.Map[H *: T, F] =:= (F[H] *: Tuple.Map[T, F])`

Scala 3 中元组的类型类派生编译器操作

Scala 3 中的类型级过滤元组

如何让匹配类型在 Scala 3 中正常工作

Scala 3:类型元组压缩

scala 3 将元组映射到元组类型的未来和返回

在 vanilla Scala 3 中表达任意元数的函数

Shapeless3 和注释

Scala 3. 实现依赖函数类型

Scala 3 中,如何替换被丢弃的General Type Projection?

Dotty 提供什么来替代字体投影?

但是无论我怎么做,我都无法进行类型检查。

恐怕这不是对您正在做的事情以及您遇到的错误的正确描述。您应该始终准备 MCVE 然后我们可以考虑您的特定编译错误。您还应该使用样本输入和理想的输出来补充 MCVE。

下面的代码似乎可以编译

trait Parser[T]

sealed trait ParseExpr[T]
case class Term[T](t: T) extends ParseExpr[T]
case class NonTerm[T](name: String) extends ParseExpr[T]
case class Alt[T](ps: List[ParseExpr[T]]) extends ParseExpr[T]
case class Cat[Ts <: Tuple](ps: Tuple.Map[Ts, ParseExpr]) extends ParseExpr[Ts]

def parserFor[T](pe: ParseExpr[T]): /*ParserFor[T]*/Parser[T] = ???

type ParserFor[T /*<: ParseExpr[?]*/] /*<: Parser[?]*/ = T match
  case ParseExpr[t] => Parser[t]

type Ps <: Tuple
val parseExpr: ParseExpr[Ps] = ???
val res = parseExpr match
  case Cat(ps) => ps.map[ParserFor]([pe_t /*<: ParseExpr[?]*/] => (pe: pe_t) => pe match
    case pe: ParseExpr[t] => parserFor[t](pe)
  )

def test(using Tuple.Map[Tuple.Map[Ps, ParseExpr], ParserFor] =:= Tuple.Map[Ps, Parser]): Unit =
  res: Tuple.Map[Ps, Parser]

Scala 3.2.2

© www.soinside.com 2019 - 2024. All rights reserved.