Scala 中的类型 lambda 是什么,它们有什么好处? [英] What are type lambdas in Scala and what are their benefits?

查看:28
本文介绍了Scala 中的类型 lambda 是什么,它们有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时我偶然发现了

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

在 Scala 博客文章中,这给了它一个我们使用了 type-lambda 技巧"的手波.

in Scala blog posts, which give it a "we used that type-lambda trick" handwave.

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

While I have some intutition about this (we gain an anonymous type parameter A without having to pollute the definition with it?), I found no clear source describing what the type lambda trick is, and what are its benefits. Is it just syntactic sugar, or does it open some new dimensions?

推荐答案

当您使用更高级的类型时,类型 lambda 很重要.

Type lambdas are vital quite a bit of the time when you are working with higher-kinded types.

考虑一个简单的例子,定义一个 monad 的正确投影.monad 类型类如下所示:

Consider a simple example of defining a monad for the right projection of Either[A, B]. The monad typeclass looks like this:

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:

Now, Either is a type constructor of two arguments, but to implement Monad, you need to give it a type constructor of one argument. The solution to this is to use a type 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]
}

这是类型系统中柯里化的一个例子——你已经柯里化了Either的类型,这样当你想创建一个EitherMonad的实例时,你必须指定其中一种类型;另一个当然是在您调用 point 或 bind 时提供的.

This is an example of currying in the type system - you have curried the type of Either, such that when you want to create an instance of EitherMonad, you have to specify one of the types; the other of course is supplied at the time you call point or bind.

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

The type lambda trick exploits the fact that an empty block in a type position creates an anonymous structural type. We then use the # syntax to get a type member.

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

In some cases, you may need more sophisticated type lambdas that are a pain to write out inline. Here's an example from my code from today:

// 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 这样的名字来引用 IterateeT monad 的类型,该类型专用于第二个 monad 的某个转换器版本,该版本专用于第三个 monad.当您开始堆叠时,这些类型的构造变得非常必要.当然,我从不实例化 FG;它只是为了让我在类型系统中表达我想要的东西.

This class exists exclusively so that I can use a name like FG[F, G]#IterateeM to refer to the type of the IterateeT monad specialized to some transformer version of a second monad which is specialized to some third monad. When you start to stack, these kinds of constructs become very necessary. I never instantiate an FG, of course; it's just there as a hack to let me express what I want in the type system.

这篇关于Scala 中的类型 lambda 是什么,它们有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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