for-comprehension yield 引发类型不匹配编译器错误
for-comprehension yield raises type mismatch compiler error
我想从 Iterable[Try[Int]]
中提取所有有效值的列表 (Iterable[Int]
)
val test = List(
Try(8),
Try(throw new RuntimeException("foo")),
Try(42),
Try(throw new RuntimeException("bar"))
)
以下是从test
打印所有有效值的方法:
for {
n <- test
p <- n
} println(p)
// Output
// 8
// 42
但是,当我尝试将有效值保存到列表时,我收到了一个错误:
val nums: Seq[Int] = for {
n <- list
p <- n // Type mismatch. Required: IterableOnce[Int], found Try[Int]
} yield(p)
println(nums)
如何修复错误以及出现错误的原因?
尝试收集
test.collect { case Success(value) => value }
// res0: List[Int] = List(8, 42)
在对应于
的理解格式中
for { Success(p) <- test } yield p
两者都使用 Constructor Patterns,它在幕后执行 isInstanceOf
类型测试,然后是 asInstanceOf
类型转换。详细地对应于
test
.filter (_.isInstanceOf[Success[Int]])
.map (_.asInstanceOf[Success[Int]].value)
下面的 for-comprehension 不起作用,因为其中的 monads 必须对齐
for {
n <- test // List monad
p <- n // does not align with Try monad
} yield (p)
以上理解脱糖为
test.flatMap((n: Try[Int]) => n.map((p: Int) => p))
并查看 flatMap
的签名,我们发现它需要一个函数
Try[Int] => IterableOnce[Int]
同时我们提供
Try[Int] => Try[Int]
因为n.map((p: Int) => p)
returnsTry[Int]
。现在下面的 for-comprehension 完全不同了[=30=]
for {
n <- test
p <- n
} println(p)
因为没有 yield
它脱糖为
test.foreach((n: Try[Int]) => n.foreach((p: Int) => println(p)))
其中 foreach
需要类型为
的函数
Try[Int] => Unit
我们确实提供了,因为 n.foreach((p: Int) => println(p))
确实 returns Unit
.
您也可以试试:
val nums: Seq[Int] = list.map(_.toOption).flatten
或
val nums: Seq[Int] = list.flatMap(_.toOption)
我想从 Iterable[Try[Int]]
中提取所有有效值的列表 (Iterable[Int]
)
val test = List(
Try(8),
Try(throw new RuntimeException("foo")),
Try(42),
Try(throw new RuntimeException("bar"))
)
以下是从test
打印所有有效值的方法:
for {
n <- test
p <- n
} println(p)
// Output
// 8
// 42
但是,当我尝试将有效值保存到列表时,我收到了一个错误:
val nums: Seq[Int] = for {
n <- list
p <- n // Type mismatch. Required: IterableOnce[Int], found Try[Int]
} yield(p)
println(nums)
如何修复错误以及出现错误的原因?
尝试收集
test.collect { case Success(value) => value }
// res0: List[Int] = List(8, 42)
在对应于
的理解格式中for { Success(p) <- test } yield p
两者都使用 Constructor Patterns,它在幕后执行 isInstanceOf
类型测试,然后是 asInstanceOf
类型转换。详细地对应于
test
.filter (_.isInstanceOf[Success[Int]])
.map (_.asInstanceOf[Success[Int]].value)
下面的 for-comprehension 不起作用,因为其中的 monads 必须对齐
for {
n <- test // List monad
p <- n // does not align with Try monad
} yield (p)
以上理解脱糖为
test.flatMap((n: Try[Int]) => n.map((p: Int) => p))
并查看 flatMap
的签名,我们发现它需要一个函数
Try[Int] => IterableOnce[Int]
同时我们提供
Try[Int] => Try[Int]
因为n.map((p: Int) => p)
returnsTry[Int]
。现在下面的 for-comprehension 完全不同了[=30=]
for {
n <- test
p <- n
} println(p)
因为没有 yield
它脱糖为
test.foreach((n: Try[Int]) => n.foreach((p: Int) => println(p)))
其中 foreach
需要类型为
Try[Int] => Unit
我们确实提供了,因为 n.foreach((p: Int) => println(p))
确实 returns Unit
.
您也可以试试:
val nums: Seq[Int] = list.map(_.toOption).flatten
或
val nums: Seq[Int] = list.flatMap(_.toOption)