0__*_*0__ 6 scala pattern-matching
有了这个基础结构:
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] = ???
}
Run Code Online (Sandbox Code Playgroud)
可以写下以下的理解:
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
}
Run Code Online (Sandbox Code Playgroud)
但是这个使用中间变量失败了:
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
}
Run Code Online (Sandbox Code Playgroud)
标记为XXX的行的错误是:
Run Code Online (Sandbox Code Playgroud)type mismatch; found : (Playground.this.Pat[Int], Playground.this.Pat[Int]) required: Playground.this.Pat[?]
Scala是2.12.4
当您map使用过度限制性签名进行定义时会发生这种情况map[B](f: Pat[A] => Pat[B]).回想一下,通常,它应该接受具有任意结果类型的函数B,也就是说,它应该是这样的:
map[B](f: A => B): <stuff>
Run Code Online (Sandbox Code Playgroud)
现在,您对中间辅助变量的理解 brown
val xs = for {
len <- lPat.bubble
brown = Pat(4, 40, 3)
cantus <- brown.grouped(len)
} yield {
cantus ++ Pat(-1)
}
Run Code Online (Sandbox Code Playgroud)
使用mapinto 重写
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))))
}))
Run Code Online (Sandbox Code Playgroud)
如文档中所述或我在此处的过于详细的答案.
注意隐式生成的返回类型map现在是什么样的(Pat[A], Pat[Int])(元组的类型(len, brown)),并且与Pat[B]声明中的模式不匹配.
我没有看到任何变通方法.尽你所能避免定义map为map[B](f: Pat[A] => Pat[B]),否则它会表现得太奇怪了.避免破坏性感map.如果你Pat[X]不能map f: X => Y为一个Pat[Y]任意X而且Y,那就不要打电话了map.
编辑:总有一个解决方法......
你可以做的一件事是介绍一些隐式提供的CanPatFrom:
trait CanPatFrom[X, A] extends (X => Pat[A])
Run Code Online (Sandbox Code Playgroud)
然后
...
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`
*/
...
}
Run Code Online (Sandbox Code Playgroud)
假设你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至少可以应对返回类型是元组的情况.
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |