scala - Scala 中的类型级编程

标签 scala type-level-computation

我想更深入地了解 Scala 中的类型级编程,因此我开始做一些小练习。我从类型级别的皮亚诺数的实现开始。这是下面的代码!

sealed trait PeanoNumType { // Type at the end indicates to the reader that we are dealing with types
  type plus[That <: PeanoNumType] <: PeanoNumType
}

sealed trait ZeroType extends PeanoNumType {
  type plus[That <: PeanoNumType] = That
}

sealed trait NextType[This <: PeanoNumType] extends PeanoNumType {
   type plus[That <: PeanoNumType] = NextType[This#plus[That]]
}

现在的问题是,上述实现会给我带来什么?我该如何使用它?

最佳答案

只要您需要自己创建这些类型,它就不会为您提供太多帮助。但是,一旦你让编译器为你做这些事情,它就会变得更有用。

在展示之前,让我们将皮亚诺算术的表示方式更改为更短的形式:

sealed trait Num
case object Zero extends Num
case class Succ[N <: Num](num: N) extends Num

然后您可以创建具有编译时已知大小的列表:

sealed abstract class List[+H, N <: Num](val size: N) {
  def ::[T >: H](value: T): List[T, Succ[N]] = Cons(value, this)
}
case object Nil extends List[Nothing, Zero.type](Zero)
case class Cons[+H, N <: Num](head: H, tail: List[H, N]) extends List[H, Succ[N]](Succ(tail.size))
type ::[+H, N <: Num] = Cons[H, N]

如果您检查使用 sych 列表创建的某物的类型,它将在其类型中编码大小:

val list = 1 :: 2 :: 3 :: 4 :: Nil // List[Int, Succ[Succ[Succ[Succ[Zero.type]]]]] = Cons(1,Cons(2,Cons(3,Cons(4,Nil))))

接下来您可以尝试做的事情是使用隐式来检查某些内容,例如

trait EvenNum[N <: Num]
implicit val zeroIsEven = new EvenNum[Zero.type] {}
implicit def evenNPlusTwo[N <: Num](implicit evenN: EvenNum[N]) = new EvenNum[Succ[Succ[N]]] {}

这样,您就可以强制执行某些操作,只有在可以提供隐式证据时才能完成:

def operationForEvenSizeList[T, N <: Num](list: List[T, N])(implicit ev: EvenNum[N]) = {
  // do something with list of even length
}

operationForEvenSizeList(1 :: 2 :: Nil) // ok
operationForEvenSizeList(1 :: 2 :: 3 :: Nil) // compiler error

据我所知,当您开始使用隐式创建新类型时,Scala 中类型级编程的真正威力就会显现出来:可用于隐式证据、类型类派生和删除某些结构样板的类型。

Shapeless 是一个对泛型编程有很大帮​​助的库。我相信,一旦您用隐含的类型类派生进行一两个练习,这对您来说将是一件有趣的事情。

回到您的代码:您可以提供一些隐式函数,这些隐式函数将为您生成并提供类的实例。另外,除了创建新类之外,这段代码还会做其他事情,例如组合您要添加到这些类中的元素列表,或者提供从 PeanoNumType 到 Int 的转换,或者添加一些在编译时工作的谓词等。Sky 是极限。

关于scala - Scala 中的类型级编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43956467/

相关文章:

arrays - 表示多维数组(张量)的类型级编程

haskell - 导入 type level naturals 的 * 运算符

haskell - 这是什么 Haskell 语法(类型级运算符?)

scala - 为什么类型级计算需要 Aux 技术?

scala - 解释 Scala 类型级编程中使用的 `LowPriorityImplicits` 模式

arrays - Scala 中的二维数组乘法

scala - Scala中元组的通用getter方法可以保留动态类型?

regex - Scala:将字符串与正则表达式列表进行匹配

scala - 在Akka Actor 中堆叠多个特征

Scala Cats效果-IO异步移位-如何工作?