1

我正在为我在微风的有关分布的文档中看到的一个示例而摸不着头脑。

创建 Rand 实例后,它们表明您可以执行以下操作:

import breeze.stats.distributions._

val pois = new Poisson(3.0);
val doublePoi: Rand[Double] = for(x <- pois) yield x.toDouble

现在,这很酷,我可以得到一个 Rand 对象,Double而不是Int在调用samples方法时得到。另一个例子可能是:

val abc = ('a' to 'z').map(_.toString).toArray
val letterDist: Rand[String] = for(x <- pois) yield {
val i = if (x > 26) x % 26 else x
abc(i)
}
val lettersSamp = letterDist.samples.take(20)
println(letterSamp)

问题是,这里发生了什么?Rand[T]不是一个集合,到目前为止我看到的所有 for/yield 示例都适用于集合。scala 文档没有提及太多,我发现的唯一一件事就是在这里翻译 for-comprehensions 。这里的基本规则是什么?这还能如何使用(不一定是轻而易举的相关答案)

4

2 回答 2

1

Scala 具有将表达式转换为等效项for和调用的规则,还可以选择使用等应用过滤器。关于如何将每个 for 理解表达式转换为等效方法调用的实际规范可以在Scala 规范的这一部分中找到。for-yieldflatMapmapwithFilter

如果我们采用您的示例并对其进行编译,我们将看到for-yield表达式发生底层转换。这是使用scalac -Xprint:typer命令打印出类型树来完成的:

val letterDist: breeze.stats.distributions.Rand[String] = 
        pois.map[String](((x: Int) => {
          val i: Int = if (x.>(26))
            x.%(26)
          else
            x;
          abc.apply(i)
}));

在这里,您可以看到它for-yield变成了单个map传入 anIntif-else在表达式内部应用。这是有效的,因为定义Rand[T]了一个map方法

def map[E](f: T => E): Rand[E] = MappedRand(outer, f)
于 2016-06-12T09:32:57.417 回答
0

因为理解只是 flatMap、map 和 withFilter 的语法糖。在 for 理解中使用的主要要求是实现这些方法。因此它们不限于集合,例如,用于理解的一些常见的非集合是 Option、Try 和 Future。

在您的情况下,泊松似乎继承自一个名为 Rand 的特征

https://github.com/scalanlp/breeze/blob/master/math/src/main/scala/breeze/stats/distributions/Rand.scala

这个 trait 定义了 map、flatmap 和 withFilter。

提示:如果您使用 IntelliJ 之类的 IDE - 您可以在 for comprehension 上按alt+ enter,然后选择转换为脱糖表达式,您将看到它是如何扩展的。

于 2016-06-12T09:31:46.550 回答