如何实现返回递归匹配类型的递归Scala 3函数?

发布于 2025-02-12 17:33:36 字数 2306 浏览 0 评论 0原文

我无法实现返回递归匹配类型的函数。例如,我从std lib中取了元组附加类型,并尝试实现一个简单的附加函数。

// Tuple append match type, copied from std lib
type Append[X <: Tuple, Y] <: Tuple = X match {
  case EmptyTuple => Y *: EmptyTuple
  case x *: xs => x *: Append[xs, Y]
}

// Types work just fine
val x: Append[(String, Int), Long] = ("", 1, 2L)

// My simple function implementation that does not compile
def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x match
  case _: EmptyTuple => y *: EmptyTuple
  case x *: xs => x *: append(xs, y)
[E007] Type Mismatch Error:
  case _: EmptyTuple => y *: EmptyTuple
                        ^^^^^^^^^^^^^^^
             Found:    Y *: EmptyTuple.type
             Required: Append[X, Y]

             where:    X is a type in method append with bounds <: Tuple


             Note: a match type could not be fully reduced:

               trying to reduce  Append[X, Y]
               failed since selector  X
               does not match  case EmptyTuple => Y *: EmptyTuple
               and cannot be shown to be disjoint from it either.
               Therefore, reduction cannot advance to the remaining case

                 case x *: xs => x *: Append[xs, Y]

 longer explanation available when compiling with `-explain`
[E007] Type Mismatch Error:
  case x *: xs => x *: append(xs, y)
                  ^^^^^^^^^^^^^^^^^^
             Found:    Any *: Append[Tuple, Y]
             Required: Append[X, Y]

             where:    X is a type in method append with bounds <: Tuple


             Note: a match type could not be fully reduced:

               trying to reduce  Append[Tuple, Y]
               failed since selector  Tuple
               does not match  case EmptyTuple => Y *: EmptyTuple
               and cannot be shown to be disjoint from it either.
               Therefore, reduction cannot advance to the remaining case

                 case x *: xs => x *: Append[xs, Y]

 longer explanation available when compiling with `-explain`

scastie

I fail to implement a function that returns a recursive match type. As an example, I took the tuple Append type from the std lib and tried to implement a simple append function.

// Tuple append match type, copied from std lib
type Append[X <: Tuple, Y] <: Tuple = X match {
  case EmptyTuple => Y *: EmptyTuple
  case x *: xs => x *: Append[xs, Y]
}

// Types work just fine
val x: Append[(String, Int), Long] = ("", 1, 2L)

// My simple function implementation that does not compile
def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x match
  case _: EmptyTuple => y *: EmptyTuple
  case x *: xs => x *: append(xs, y)
[E007] Type Mismatch Error:
  case _: EmptyTuple => y *: EmptyTuple
                        ^^^^^^^^^^^^^^^
             Found:    Y *: EmptyTuple.type
             Required: Append[X, Y]

             where:    X is a type in method append with bounds <: Tuple


             Note: a match type could not be fully reduced:

               trying to reduce  Append[X, Y]
               failed since selector  X
               does not match  case EmptyTuple => Y *: EmptyTuple
               and cannot be shown to be disjoint from it either.
               Therefore, reduction cannot advance to the remaining case

                 case x *: xs => x *: Append[xs, Y]

 longer explanation available when compiling with `-explain`
[E007] Type Mismatch Error:
  case x *: xs => x *: append(xs, y)
                  ^^^^^^^^^^^^^^^^^^
             Found:    Any *: Append[Tuple, Y]
             Required: Append[X, Y]

             where:    X is a type in method append with bounds <: Tuple


             Note: a match type could not be fully reduced:

               trying to reduce  Append[Tuple, Y]
               failed since selector  Tuple
               does not match  case EmptyTuple => Y *: EmptyTuple
               and cannot be shown to be disjoint from it either.
               Therefore, reduction cannot advance to the remaining case

                 case x *: xs => x *: Append[xs, Y]

 longer explanation available when compiling with `-explain`

Scastie

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瞎闹 2025-02-19 17:33:36

在返回比赛类型方面,编译器非常挑剔。您的第二种情况需要进行少量修改以使其在没有演员的情况下工作( scastie

def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x.match {
  case _: EmptyTuple => y *: EmptyTuple
  case (x *: xs): (x *: xs) => x *: append(xs, y)
}

:(x *:xs),编译器不明白您的函数的第二种情况与匹配类型的第二种情况相对应。也许将来会更聪明。

The compiler is very fussy when it comes to returning match types. Your second case needs a small modification to get it to work without the cast (Scastie):

def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x.match {
  case _: EmptyTuple => y *: EmptyTuple
  case (x *: xs): (x *: xs) => x *: append(xs, y)
}

Without the : (x *: xs), the compiler doesn't understand that your function's second case corresponds with the second case of the match type. Perhaps in the future it'll be smarter.

匿名的好友 2025-02-19 17:33:36

附加函数中的铸件可以做到这一点。我无法内联它,但这暂时就足够了。

// Tuple append match type, copied from std lib
type Append[X <: Tuple, Y] <: Tuple = X match {
  case EmptyTuple => Y *: EmptyTuple
  case x *: xs => x *: Append[xs, Y]
}

// Types work just fine
val x: Append[(String, Int), Long] = ("", 1, 2L)

// Function now compiles and succeeds at runtime
def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x.match {
  case _: EmptyTuple => y *: EmptyTuple
  case x *: xs => x *: append(xs, y)
}.asInstanceOf[Append[X, Y]]

append((1, 2), 3)

scastie

A cast in the append function did the trick. I couldn't manage to inline it, but this is sufficient for now.

// Tuple append match type, copied from std lib
type Append[X <: Tuple, Y] <: Tuple = X match {
  case EmptyTuple => Y *: EmptyTuple
  case x *: xs => x *: Append[xs, Y]
}

// Types work just fine
val x: Append[(String, Int), Long] = ("", 1, 2L)

// Function now compiles and succeeds at runtime
def append[X <: Tuple, Y](x: X, y: Y): Append[X, Y] = x.match {
  case _: EmptyTuple => y *: EmptyTuple
  case x *: xs => x *: append(xs, y)
}.asInstanceOf[Append[X, Y]]

append((1, 2), 3)

Scastie

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文