理解产量会导致类型不匹配的编译器错误 [英] for-comprehension yield raises type mismatch compiler error

查看:94
本文介绍了理解产量会导致类型不匹配的编译器错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从Iterable[Try[Int]]中提取所有有效值(Iterable[Int])的列表

I want to extract from Iterable[Try[Int]] a list of all valid values (Iterable[Int])

val test = List(
    Try(8), 
    Try(throw new RuntimeException("foo")), 
    Try(42), 
    Try(throw new RuntimeException("bar"))
)

以下是从test打印所有有效值的方法:

The following is the way to print all valid values from test:

for {
    n <- test
    p <- n
} println(p)

// Output
// 8
// 42

但是,当我尝试将有效值保存到列表中时,出现了错误:

However, when I tried to save the valid values to list I have received an error:

val nums: Seq[Int] = for {
    n <- list
    p <- n    // Type mismatch. Required: IterableOnce[Int], found Try[Int]
} yield(p)
println(nums)

如何解决该错误以及为何引发该错误?

How to fix the error and why it was raised?

推荐答案

尝试收集

test.collect { case Success(value) => value }
// res0: List[Int] = List(8, 42)

采用对应的理解格式

for { Success(p) <- test } yield p

两者都使用构造函数在引擎盖下执行isInstanceOf型式测试并随后进行asInstanceOf型式转换的图案.也许对应于类似

Both make use of Constructor Patterns which under the hood perform isInstanceOf type test followed by asInstanceOf type cast. Verbosly that corresponds to something like

test
  .filter (_.isInstanceOf[Success[Int]])
  .map    (_.asInstanceOf[Success[Int]].value)

下面的理解不起作用,因为其中的单子必须对齐

The following for-comprehension does not work because the monads in it have to align

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的签名,我们看到它期望一个功能

and looking at the signature of flatMap we see it expects a function

Try[Int] => IterableOnce[Int]

我们提供

Try[Int] => Try[Int]

因为n.map((p: Int) => p)返回Try[Int].现在,以下的理解是完全不同的野兽

because n.map((p: Int) => p) returns Try[Int]. Now the following for-comprehension is a whole different beast

for {
    n <- test
    p <- n
} println(p)

由于缺少yield,因此对

because of the absence of yield it desugars to

test.foreach((n: Try[Int]) => n.foreach((p: Int) => println(p)))

其中foreach需要一个类型的函数

where foreach expects a function of type

Try[Int] => Unit

我们确实提供了

,因为n.foreach((p: Int) => println(p))确实返回了Unit.

which we indeed provide because n.foreach((p: Int) => println(p)) indeed returns Unit.

这篇关于理解产量会导致类型不匹配的编译器错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆