理解 Scala 类型系统中的 Aux 模式 [英] Understanding the Aux pattern in Scala Type System

查看:48
本文介绍了理解 Scala 类型系统中的 Aux 模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题之前可能有人问过和回答过,但我想通过一个例子来理解这一点,我无法推理出 Aux 模式可能有帮助的地方!所以这是特征:

This question may be asked and answered before, but I would like to understand this with an example and I could not reason out where the Aux pattern might be helpful! So here is the trait:

trait Foo[A] {
  type B
  def value: B
}

为什么我有一个类型绑定到值函数的返回类型?我这样做能达到什么目的?特别是,我会在哪里使用这些模式?

Why do I have a type that is kind of bound to the return type of the value function? What do I achieve doing this? In particular, where would I use such patterns?

推荐答案

想象一个用于获取任何元组的最后一个元素的类型类.

Imagine a typeclass for getting the last element of any tuple.

trait Last[A] {
  type B
  def last(a: A): B
}

object Last {
  type Aux[A,B0] = Last[A] { type B = B0 }

  implicit def tuple1Last[A]: Aux[Tuple1[A],A] = new Last[Tuple1[A]] {
    type B = A
    def last(a: Tuple1[A]) = a._1
  }

  implicit def tuple2Last[A,C]: Aux[(A,C),C] = new Last[(A,C)] {
    type B = C
    def last(a: (A,C)) = a._2
  }

  ...
}

B 的类型总是依赖于 A 的类型,这就是为什么 A 是 typeclass 的输入类型而 B 是一种输出类型.

The type B always depends on the type A, that's why A is an input type of the typeclass and B is an output type.

现在,如果您想要一个可以根据最后一个元素对任何元组列表进行排序的函数,您需要访问同一参数列表中的 B 类型.这就是在 Scala 的当前状态下为什么需要 Aux 模式的主要原因:目前不可能在同一参数列表中引用 last.B 类型如定义 last 的地方,也不可能有多个隐式参数列表.

Now if you want a function that can sort any list of tuples based on the last element you need access to the B type in the same argument list. That's the main reason, in the current state of Scala, why you need the Aux pattern: currently it's not possible to refer to the last.B type in the same parameter list as where last is defined, nor is it possible to have multiple implicit parameter lists.

def sort[A,B](as: List[A])(implicit last: Last.Aux[A,B], ord: Ordering[B]) = as.sortBy(last.last)

当然,你总是可以完整地写出 Last[A] { type B = B0 } ,但显然这很快就变得非常不切实际(想象一下添加更多具有依赖类型的隐式参数,这在 Shapeless 中很常见);这就是 Aux 类型别名的用武之地.

Of course you can always write Last[A] { type B = B0 } out in full, but obviously that becomes very impractical very quickly (imagine adding a couple more implicit parameters with dependent types, something that's very common with Shapeless); that's where the Aux type alias comes in.

这篇关于理解 Scala 类型系统中的 Aux 模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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