gpt4 book ai didi

scala - 使用中间变量时理解失败

转载 作者:行者123 更新时间:2023-12-04 14:08:53 26 4
gpt4 key购买 nike

Scastie version

有了这个基础设施:

trait Pat[A]
object Pat {
def apply[A](elems: A*): Pat[A] = ???
}

implicit class PatOps[A](p: Pat[A]) {
def ++ (that: Pat[A]): Pat[A] = ???

def bubble: Pat[Pat[A]] = ???

def grouped(size: Pat[Int]): Pat[Pat[A]] = ???
}

implicit class PatPatOps[A](p: Pat[Pat[A]]) {
def map[B](f: Pat[A] => Pat[B]): Pat[Pat[B]] = ???

def flatMap[B](f: Pat[A] => Pat[B]): Pat[B] = ???

def flatten: Pat[A] = ???
}

可以写出以下 for-comprehension:
trait Test1 {
val lPat = Pat(1, 2, 3)
val xs = for {
len <- lPat.bubble
cantus <- Pat(4, 40, 3).grouped(len)
} yield {
cantus ++ Pat(-1)
}
xs.flatten
}

但是这个使用中间变量的方法失败了:
trait Test2 {
val lPat = Pat(1, 2, 3)
val xs = for {
len <- lPat.bubble // XXX
brown = Pat(4, 40, 3)
cantus <- brown.grouped(len)
} yield {
cantus ++ Pat(-1)
}
xs.flatten
}

标记为 XXX 的行的错误是:

type mismatch;
found : (Playground.this.Pat[Int], Playground.this.Pat[Int])
required: Playground.this.Pat[?]


斯卡拉是 2.12.4

最佳答案

当您定义 map 时会发生这种情况签名过于严格 map[B](f: Pat[A] => Pat[B]) .回想一下,通常应该接受具有任意结果类型的函数 B ,也就是说,它应该是这样的:

map[B](f: A => B): <stuff>

现在,您对中间辅助变量 brown 的理解
  val xs = for {
len <- lPat.bubble
brown = Pat(4, 40, 3)
cantus <- brown.grouped(len)
} yield {
cantus ++ Pat(-1)
}

使用 map 重写进入
  val xs = lPat.bubble.map(((len) => {
val brown = Pat(4, 40, 3);
scala.Tuple2(len, brown)
})).flatMap(((x$1) => x$1: @scala.unchecked match {
case scala.Tuple2((len @ _), (brown @ _)) =>
brown.
grouped(len).
map(((cantus) => cantus.$plus$plus(Pat(-1))))
}))

the documentation 中所述或 in my overly detailed answer here .

注意隐式生成的返回类型 map现在类似于 (Pat[A], Pat[Int]) (元组的类型 (len, brown) ),并且与模式 Pat[B] 不匹配从你的声明。

我没有看到任何解决方法。尽你所能避免定义 mapmap[B](f: Pat[A] => Pat[B]) ,否则它的行为会太奇怪了。避免破坏 map 的功能性.如果您的 Pat[X]不能 map f: X => YPat[Y]为任意 XY ,那就别叫它 map .

编辑:总有一个变通方法...

您可以做的一件事是引入某种隐式提供的 CanPatFrom :
trait CanPatFrom[X, A] extends (X => Pat[A])

进而
...
def map[X, B](f: Pat[A] => X)(implicit cpf: CanPatFrom[X, B]) = {
val pb: Pat[B] = cpf(f(...))
/* do your stuff here with `Pat[B]` instead of
* generic `X`
*/
...
}

假设您的 Pat带有某种笛卡尔-幺半群结构,你可以定义
  • CanPatFrom[Pat[A], Pat[A]] ,
  • CanPatFrom[(Pat[A], Pat[B]), Pat[(A, B)]] ,
  • CanPatFrom[(Pat[A], Pat[B], Pat[C]), Pat[(A, B, C)]] ,
  • ...

  • 从而获得 map这至少可以应对返回类型是元组的情况。

    关于scala - 使用中间变量时理解失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48992214/

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