为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

什么是Scala中的lambda类型,它们有什么好处?有时我偶然发现了半神秘的符号def f[T](..) = new T[({type l[A]=SomeType[A,..]})#l] {..}在Scala博客文章中,它给了它一个“我们使用那种类型 - lambda技巧”的手动波。虽然我对此有一些说明(我们获得了一个匿名类型参数A而不必用它来污染定义?),我发现没有明确的来源描述类型lambda技巧是什么,以及它有什么好处。它只是语法糖,还是开了一些新的维度?
查看完整描述

3 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

当你使用更高级的类型时,类型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]}

现在,要么是两个参数的类型构造函数,但要实现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的一个示例 - 您已经知道了Either的类型,这样当您想要创建EitherMonad的实例时,您必须指定其中一种类型; 另一方面当然是在你调用point或bind时提供的。

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

在某些情况下,您可能需要更复杂的类型lambda,这是写内联的痛苦。这是我今天的代码中的一个例子:

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

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


查看完整回答
反对 回复 2019-08-06
?
PIPIONE

TA贡献1829条经验 获得超9个赞

其好处与匿名函数赋予的好处完全相同。

def inc(a: Int) = a + 1; List(1, 2, 3).map(inc)List(1, 2, 3).map(a => a + 1)

使用Scalaz 7的一个示例用法。我们想要使用一个Functor可以在一个函数中映射第二个元素的函数Tuple2

type IntTuple[+A]=(Int, A)Functor[IntTuple].map((1, 2))(a => a + 1)) // (1, 3)Functor[({type l[a] = (Int, a)})#l].map((1, 2))(a => a + 1)) // (1, 3)

Scalaz提供了一些可以推断类型参数的隐式转换Functor,因此我们经常避免完全编写这些转换。上一行可以重写为:

(1, 2).map(a => a + 1) // (1, 3)

如果使用IntelliJ,则可以启用“设置”,“代码样式”,“Scala”,“折叠”,“键入Lambdas”。然后,这隐藏了语法的苛刻部分,并呈现更可口:

Functor[[a]=(Int, a)].map((1, 2))(a => a + 1)) // (1, 3)

Scala的未来版本可能直接支持这种语法。


查看完整回答
反对 回复 2019-08-06
  • 3 回答
  • 0 关注
  • 828 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信