Scala for-comprehension with 元组分解
Scala for-comprehension with tuple decomposition
for {
a <- Some(1)
b <- Some(2)
} yield (a, b)
returns Some((1, 2))
for {
a <- Right(1).right
b <- Left(2).left
} yield (a, b)
returns Left((1, 2))
现在我想分解 for comprehension 中的元组。
for {
(a, b) <- Some((1, 2))
(c, d) <- Some((3, 4))
} yield (a, b, c, d)
returns Some((1, 2, 3, 4))
for {
(a, b) <- Right((1, 2)).right
(c, d) <- Left((3, 4)).left
} yield (a, b, c, d)
编译失败:
error: constructor cannot be instantiated to expected type;
found : (T1, T2)
required: scala.util.Either[Nothing,(Int, Int)]
(a, b) <- Right((1, 2)).right
error: constructor cannot be instantiated to expected type;
found : (T1, T2)
required: scala.util.Either[(Int, Int),Nothing]
为什么最后一个示例不起作用?有什么区别?
这可能是 for 表达式的限制。翻译
for {
(a, b) <- Some((1, 2))
(c, d) <- Some((3, 4))
} yield (a, b, c, d)
进入
Some((1, 2)).flatMap({case(a, b) =>
Some((3, 4)).map({case (c, d) =>
(a, b, c, d)
})
})
双向工作。使用 Either
表达式,只有 map/flatMap
版本有效。
for {
(a, b) <- Right((1, 2)).right
(c, d) <- Left((3, 4)).left
} yield (a, b, c, d)
Right((1, 2)).right.flatMap({
case(a, b) => Left((3, 4)).left.map({case (c, d) =>
(a, b, c, d)
})
})
我不建议使用 Either
,而是使用来自 \/
的类型
鳞鳞鱼。 http://eed3si9n.com/learning-scalaz/Either.html Either
不是
左倾或右倾,这是一个问题,因为它没有指定
错误或值的去向。
因为 (Any, Any) <- Either 的生成器不是 "irrefutable" 过滤器被添加到去糖代码中 (why does filter have to be defined for pattern matching in a for loop in scala?),导致:
Right((1, 2)).right.filter { case (a, b) => true; case _ => false }.flatMap({
case(a, b) => Left((3, 4)).left.filter { case (c, d) => true; case _ => false }.map({case (c, d) =>
(a, b, c, d)
})
})
过滤器是编译错误的地方,因为右边的过滤器方法是这样的(左边的类似):
def filter[X](p: B => Boolean): Option[Either[X, B]] = e match {
case Left(_) => None
case Right(b) => if(p(b)) Some(Right(b)) else None
}
这意味着编译器正在尝试执行以下操作:
(T1, T2) match {
case Left(_) => None
case Right(b) => if(p(b)) Some(Right(b)) else None
}
失败,因为 (T1, T2) 无法转换为 Either[A, B](右延伸),其中 A 为 Nothing,B 为 (Int, Int)。
您可以通过以下方式获得接近于此的结果:
for {
a <- Right((1, 2)).right
b <- Left((3, 4)).left
} yield (a, b) match {
case ((c, d), (e, f)) => (c, d, e, f)
case _ =>
}
这是一个错误:
withFilter()
被调用(一些文档引用 filter()
,但在 2.8 中已更改),这会混淆类型推断。
withFilter()
用于 for(a <- b if c)
之类的东西,但根据 6.19 它不应该在这种情况下使用。
后一个bug在已经开放七年(2008年)的SI-1336: spec requires type checking of for-comprehension to consider refutability中捕获。
也许后代会找到解决方法。
见why does filter have to be defined for pattern matching in a for loop in scala?
for {
a <- Some(1)
b <- Some(2)
} yield (a, b)
returns Some((1, 2))
for {
a <- Right(1).right
b <- Left(2).left
} yield (a, b)
returns Left((1, 2))
现在我想分解 for comprehension 中的元组。
for {
(a, b) <- Some((1, 2))
(c, d) <- Some((3, 4))
} yield (a, b, c, d)
returns Some((1, 2, 3, 4))
for {
(a, b) <- Right((1, 2)).right
(c, d) <- Left((3, 4)).left
} yield (a, b, c, d)
编译失败:
error: constructor cannot be instantiated to expected type;
found : (T1, T2)
required: scala.util.Either[Nothing,(Int, Int)]
(a, b) <- Right((1, 2)).right
error: constructor cannot be instantiated to expected type;
found : (T1, T2)
required: scala.util.Either[(Int, Int),Nothing]
为什么最后一个示例不起作用?有什么区别?
这可能是 for 表达式的限制。翻译
for {
(a, b) <- Some((1, 2))
(c, d) <- Some((3, 4))
} yield (a, b, c, d)
进入
Some((1, 2)).flatMap({case(a, b) =>
Some((3, 4)).map({case (c, d) =>
(a, b, c, d)
})
})
双向工作。使用 Either
表达式,只有 map/flatMap
版本有效。
for {
(a, b) <- Right((1, 2)).right
(c, d) <- Left((3, 4)).left
} yield (a, b, c, d)
Right((1, 2)).right.flatMap({
case(a, b) => Left((3, 4)).left.map({case (c, d) =>
(a, b, c, d)
})
})
我不建议使用 Either
,而是使用来自 \/
的类型
鳞鳞鱼。 http://eed3si9n.com/learning-scalaz/Either.html Either
不是
左倾或右倾,这是一个问题,因为它没有指定
错误或值的去向。
因为 (Any, Any) <- Either 的生成器不是 "irrefutable" 过滤器被添加到去糖代码中 (why does filter have to be defined for pattern matching in a for loop in scala?),导致:
Right((1, 2)).right.filter { case (a, b) => true; case _ => false }.flatMap({
case(a, b) => Left((3, 4)).left.filter { case (c, d) => true; case _ => false }.map({case (c, d) =>
(a, b, c, d)
})
})
过滤器是编译错误的地方,因为右边的过滤器方法是这样的(左边的类似):
def filter[X](p: B => Boolean): Option[Either[X, B]] = e match {
case Left(_) => None
case Right(b) => if(p(b)) Some(Right(b)) else None
}
这意味着编译器正在尝试执行以下操作:
(T1, T2) match {
case Left(_) => None
case Right(b) => if(p(b)) Some(Right(b)) else None
}
失败,因为 (T1, T2) 无法转换为 Either[A, B](右延伸),其中 A 为 Nothing,B 为 (Int, Int)。
您可以通过以下方式获得接近于此的结果:
for {
a <- Right((1, 2)).right
b <- Left((3, 4)).left
} yield (a, b) match {
case ((c, d), (e, f)) => (c, d, e, f)
case _ =>
}
这是一个错误:
withFilter()
被调用(一些文档引用 filter()
,但在 2.8 中已更改),这会混淆类型推断。
withFilter()
用于 for(a <- b if c)
之类的东西,但根据 6.19 它不应该在这种情况下使用。
后一个bug在已经开放七年(2008年)的SI-1336: spec requires type checking of for-comprehension to consider refutability中捕获。
也许后代会找到解决方法。
见why does filter have to be defined for pattern matching in a for loop in scala?