1

Scala 3 从属类型

 3 years ago
source link: https://blog.oyanglul.us/scala/dotty/dependent-types
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Scala 3 从属类型

Scala 3 从属类型

Table of Contents

中文 | English


可以跑的源码在这里 👉 https://github.com/jcouyang/meow


Scala 2

如果经常使用 Shapeless, 你可能会熟悉一种叫 Aux 的 Pattern 这个pattern经常用来推倒输出类型

trait Second[L <: HList] {
  type Out
  def apply(value: L): Out
}

object Second {
  type Aux[L <: HList, O] = Second[L] { type Out = O }

  def apply[L <: HList](implicit inst: Second[L]): Aux[L, inst.Out] =
    inst
}

Second(1 :: "2" :: HNil)
"2"

可以看见这个 Second 是 dependent types, 也就是说他的类型取决于输入的类型, 比如现在换一个 HList,他的 输出就不是 String 了:

Second("1" :: 2 :: HNil)
// => 2

输入变成 Int 了。

Scala 3

在 Scala 3 我们不仅可以用dependent methods,还可以声明 dependent function https://dotty.epfl.ch/docs/reference/new-types/dependent-function-types.html 。 也就是上面那个例子,可以进一步的简化:

trait Second[L <: HList] {
  type Out
  def apply(value: L): Out
}

object Second {
  def apply[L <: HList](value: L) = (inst: Second[L]) ?=> inst(value)
}

其中 ?=> https://dotty.epfl.ch/docs/reference/contextual/context-bounds.html 里面的问号并不是我的typo,这是简写的 (using inst: Second[L]) => inst(value)

注意看前后的区别:

- def apply[L <: HList](implicit inst: Second[L]): Aux[L, inst.Out] =
    inst
+ def apply[L <: HList](value: L) = (inst: Second[L]) ?=> inst(value)

以前需要标明method类型为dependent types Aux[L, inst.Out]

现在你看,我们可以把 Aux 和 Out 消除掉,因为你可以直接返回一个 dependent function

如果你给这个 dependent function 标类型的话:

def apply[L <: HList](value: L): (inst: Second[L]) ?=> inst.Out =
 (inst: Second[L]) ?=> inst(value)

它就跟Scala 2 dependent method的时候很像了,但是我们还是不用 Aux 类型的帮助。

如果懒得拉源代码下来玩,可以在 scastie 上试试 https://scastie.scala-lang.org/fyxXSR3ASj6rSkkERnUK7g


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK