加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala类型级别编程 – 代表层次结构

发布时间:2020-12-16 21:32:52 所属栏目:安全 来源:网络整理
导读:我正在 Scala中学习类型级编程,如果可以使用类型级编程来表示树或层次结构,我很好奇. 简单的情况将是一个多层次的树 A_ | B_ |C |D | E 一个人如何代表这样一个结构? 解决方法 有很多方法可以在Scala中表示异构树,其中最简单的就是这样: type MyTreeShape[
我正在 Scala中学习类型级编程,如果可以使用类型级编程来表示树或层次结构,我很好奇.

简单的情况将是一个多层次的树

A_
  |
  B_
    |C
    |D
  |     
  E

一个人如何代表这样一个结构?

解决方法

有很多方法可以在Scala中表示异构树,其中最简单的就是这样:

type MyTreeShape[A,B,C,D,E] = (A,(B,(C,D),E))

这有一些限制(尽管如此,由于我们在表示中使用元组,所以您不能将元组作为叶的值).对于其余的答案,我将使用一个稍微更复杂的代表,涉及Shapeless的HList:

import shapeless._

type MyTreeShape[A,E] =
  A ::
    (B ::
      (C :: HNil) ::
      (D :: HNil) ::
      HNil) ::
    (E :: HNil) ::
    HNil

这里一棵树是一个高分子,其头是价值,尾巴是树木的高分子.

如果我们想对这些树进行有用的通用,我们需要一些类型类.作为示例,我将在Shapeless的ops.hlist包中类型类的模型上写出一个快速深入的第一个FlattenTree.尺寸,深度等的其他类型类可以类似地实现.

这是类型类和方便的方法,使其易于使用:

trait FlattenTree[T <: HList] extends DepFn1[T] { type Out <: HList }

def flattenTree[T <: HList](t: T)(implicit f: FlattenTree[T]): f.Out = f(t)

现在对于我们将放在随播对象中的实例:

object FlattenTree {
  type Aux[T <: HList,Out0 <: HList] = FlattenTree[T] { type Out = Out0 }

  implicit def flattenTree[H,T <: HList](implicit
    tf: FlattenForest[T]
  ): Aux[H :: T,H :: tf.Out] = new FlattenTree[H :: T] {
    type Out = H :: tf.Out

    def apply(t: H :: T): H :: tf.Out = t.head :: tf(t.tail)
  }
}

请注意,这需要一个帮助类型的类FlattenForest:

trait FlattenForest[F <: HList] extends DepFn1[F] { type Out <: HList }

object FlattenForest {
  type Aux[F <: HList,Out0 <: HList] = FlattenForest[F] { type Out = Out0 }

  implicit val hnilFlattenForest: Aux[HNil,HNil] = new FlattenForest[HNil] {
    type Out = HNil

    def apply(f: HNil): HNil = HNil
  }

  implicit def hconsFlattenForest[
    H <: HList,OutH <: HList,T <: HList,OutT <: HList
  ](implicit
    hf: FlattenTree.Aux[H,OutH],tf: Aux[T,OutT],pp: ops.hlist.Prepend[OutH,OutT]
  ): Aux[H :: T,pp.Out] = new FlattenForest[H :: T] {
    type Out = pp.Out

    def apply(f: H :: T): pp.Out = pp(hf(f.head),tf(f.tail))
  }
}

现在我们可以这样使用:

val myTree: MyTreeShape[String,Int,Char,Symbol,Double] =
  "foo" :: (10 :: HList('a') :: HList('z) :: HNil) :: HList(0.0) :: HNil

val flattened = flattenTree(myTree)

让我们来看一下静态类型是否合适:

flattened: String :: Int :: Char :: Symbol :: Double :: HNil

这正是我们想要的.

你可以做到这一切没有Shapeless,但它将涉及一个令人难以置信的数量的样板.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读