gpt4 book ai didi

Scala - 创建类型集合的惯用方式

转载 作者:行者123 更新时间:2023-12-01 03:04:08 24 4
gpt4 key购买 nike

问题

假设我有一个看起来像这样的 ADT

sealed trait TT
case class A(...) extends TT
case class B(...) extends TT
case class C(...) extends TT
// ... lot of others

我有这个函数为 TT 的子集返回 true .比方说 AC .

def shouldIPublish(tt: TT): Boolean = ???

约束
  • tt我们收到来自 SortedSet我真的无法改变。下面是函数 shouldIPublish被称为:tts.exists(shouldIPublish) ( ttsSortedSet[TT] )。它被删除。
  • 我希望我的代码是可测试的。对于我目前的解决方案,这是不可能的。 (见下文)
  • 代码应该为每个 TT 编译类型。如果实际类型为tt位于子集(即 AC )中返回 true否则 false .

  • 我不完美的解决方案

    val shouldIPublishPF: PartialFunction[TT, Unit] = {
    case _: A =>
    case _: C =>
    }
    def shouldIPublish(tt: TT): Boolean = shouldIPublishPF.isDefinedAt(tt)

    我在这里使用偏函数是因为实际问题有点复杂。我用 orElse将几个偏函数组合在一起。

    这个解决方案很容易推理,也很简单。但,
  • 这似乎不是很惯用。我的意思是这个工具(部分函数)似乎不适合这项工作(测试类型是否包含在一组类型中)。
  • 我无法获得为偏函数定义的每个值 .在这种情况下,它将是 AC .当向部分函数添加新类型时,我的单元测试应该会失败。

  • 替代方案(我能想到)

    类集

    也许是最简单的解决方案。我可以有一个 Set并与 .getClass 一起上课.虽然看起来很丑。
    Set(A.getClass, C.getClass)

    无形的副产品

    起初看起来很有希望。非常地道。

    type ShoudIPublish = A :+: C :+: CNil

    不幸的是,我不知道如何测试 ShoudIPublish 中是否“包含”了一个类型。 .而且我不知道我们是否可以收集所有类型的列表(这里是 AC )。

    你有什么建议吗?

    最佳答案

    类型类看起来像一个解决方案(如果你知道 tt 的类型,即在编译时 TT 的特定子类型)

    trait ShouldIPublish[T <: TT]
    object ShouldIPublish {
    implicit val a: ShouldIPublish[A] = null
    implicit val c: ShouldIPublish[C] = null
    }

    def shouldIPublish[T <: TT : ShouldIPublish](tt: T) = ???

    shouldIPublish(A())
    // shouldIPublish(B()) // doesn't compile
    shouldIPublish(C())

    标准类型类是 shapeless.ops.coproduct.Inject
    type ShoudIPublish = A :+: C :+: CNil

    def shouldIPublish[T <: TT : Inject[ShoudIPublish, *]](tt: T) = ???

    shouldIPublish(A())
    // shouldIPublish(B()) // doesn't compile
    shouldIPublish(C())

    OOP 风格的解决方案是使用特征(如果您可以修改层次结构)
    trait ShouldIPublish

    sealed trait TT
    case class A() extends TT with ShouldIPublish
    case class B() extends TT
    case class C() extends TT with ShouldIPublish

    def shouldIPublish[T <: TT with ShouldIPublish](tt: T) = ???

    shouldIPublish(A())
    // shouldIPublish(B()) // doesn't compile
    shouldIPublish(C())

    当您不知道 TT 的特定子类型时,模式匹配解决方案可以在运行时工作在编译时
    def shouldIPublish(tt: TT) = tt match {
    case _: A => println("A")
    case _: C => println("C")
    }

    shouldIPublish(A(): TT)// A
    shouldIPublish(B(): TT)// MatchError
    shouldIPublish(C(): TT)// C

    或者
    trait ShouldIPublish

    sealed trait TT
    case class A() extends TT with ShouldIPublish
    case class B() extends TT
    case class C() extends TT with ShouldIPublish

    def shouldIPublish(tt: TT) = tt match {
    case _: ShouldIPublish => println("A or C")
    }

    shouldIPublish(A(): TT)// A or C
    shouldIPublish(B(): TT)// MatchError
    shouldIPublish(C(): TT)// A or C

    关于Scala - 创建类型集合的惯用方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59272478/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com