scala - Scala 中的 lambda 类型是什么?它们有什么好处?

标签 scala types

有时我偶然发现了半神秘的符号

def f[T](..) = new T[({type l[A]=SomeType[A,..]})#l] {..} 

在 Scala 博客文章中,它给出了“我们使用了 type-lambda 技巧”的手势。

虽然我对此有一些直觉(我们获得了一个匿名类型参数 A 而不必用它污染定义?),但我没有找到明确的来源来描述 lambda 类型技巧是什么,并且它有什么好处。它只是语法糖,还是打开了一些新的维度?

最佳答案

当您使用更高级的类型时,类型 lambda 在很多时候都至关重要。

考虑一个为 Either[A, B] 的右投影定义 monad 的简单示例。 monad 类型类如下所示:

trait Monad[M[_]] {
  def point[A](a: A): M[A]
  def bind[A, B](m: M[A])(f: A => M[B]): M[B]
}

现在,Either 是两个参数的类型构造函数,但要实现 Monad,您需要为其提供一个参数的类型构造函数。解决这个问题的方法是使用 lambda 类型:

class EitherMonad[A] extends Monad[({type λ[α] = Either[A, α]})#λ] {
  def point[B](b: B): Either[A, B]
  def bind[B, C](m: Either[A, B])(f: B => Either[A, C]): Either[A, C]
}

这是类型系统中柯里化(Currying)的一个示例 - 您已经柯里化(Currying)了 Either 的类型,这样当您想要创建 EitherMonad 的实例时,您必须指定其中一种类型;另一个当然是在您调用点或绑定(bind)时提供的。

类型 lambda 技巧利用了这样一个事实:类型位置中的空 block 会创建匿名结构类型。然后我们使用 # 语法来获取类型成员。

在某些情况下,您可能需要更复杂的类型 lambda,但内联编写起来很困难。这是我今天的代码中的一个示例:

// types X and E are defined in an enclosing scope
private[iteratee] class FG[F[_[_], _], G[_]] {
  type FGA[A] = F[G, A]
  type IterateeM[A] = IterateeT[X, E, FGA, A] 
}

这个类的存在是为了让我可以使用像 FG[F, G]#IterateeM 这样的名称来引用专门用于第二个 monad 的某些转换器版本的 IterateeT monad 的类型,而第二个 monad 专门用于某些第三个 monad。当你开始堆叠时,这些类型的构造就变得非常必要。当然,我从不实例化 FG;它只是作为一种技巧让我在类型系统中表达我想要的内容。

关于scala - Scala 中的 lambda 类型是什么?它们有什么好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8736164/

相关文章:

java - Intellij scala项目不支持swing

mysql - 多个值存储在 MySQL 数据库的单个列中?

php - User agent header - mysql存储的缩写

c++ - 二进制运算符的类型 'int' 和 'double(double*, double*, int)' 的操作数无效

list - Haskell类型的数学问题

scala - 在 ScalaTest + Mockito 中使用 Slick 模拟数据库并测试更新

java - Pyspark 列表到 Scala 序列

scala - 找到 Spark 的 Scala 安装

scala - 从 SparkSession 检索 SparkContext

c - 返回类型是否节省空间或时间