【问题标题】:Can type classes be applied to sealed traits?类型类可以应用于密封特征吗?
【发布时间】:2018-01-17 03:13:57
【问题描述】:

是否可以有一个应用于密封特征的类型类?

以下封印特质

sealed trait MyType
object Type1 extends MyType
object Type2 extends MyType
case class Type3(i:Int) extends MyType

我想用一个可以使用以下类型类表示的“显示”函数来丰富这个特征

trait Show[A] { def show(a: A): String }

我想在一个接受特征作为输入的函数中使用它

def show[A :< MyType](a: A)(implicit sh: Show[A]) = sh.show(a) // Will not compile

通常我可以做类似的事情

 implicit val type3CanShow: Show[Type3] =
new Show[Type3] {
  def show(t: Type3): String = s"show ${t.i}"
}

要让它工作,我有两个问题: 1)如何在对象而不是类上定义类型类(即Type1和Type 2) 2)我如何让它接受一个特性的工作,并确保为密封特性的 3 个产品提供类型类

为了解决 2,我可以做类似的事情(不编译 - 假设所有 3 都是案例类)

def show[A :< MyType](a: A)(implicit sh: Show[A]) =
  a match { 
     case t: Type1 =>  sh.show(t)
     case t: Type2 =>  sh.show(t)
     case t: Type3 =>  sh.show(t)
  }

更新: @thesamet 解决了 1。但是,我仍然想要一个更好的方法来做 2。 运行这样的代码,无需从上面添加模式匹配 def doSomething(t: MyType) = { show(t) }

【问题讨论】:

    标签: scala


    【解决方案1】:

    你粘贴的代码

    def show[A :< MyType](a: A)(implicit sh: Show[A]) = sh.show(a) // Will not compile
    

    无法编译,因为它应该是 &lt;: 而不是 :&lt; 来指定 MyType 作为 A 的上限。以下内容可以编译:

    def show[A <: MyType](a: A)(implicit sh: Show[A]) = sh.show(a)
    

    要为Type1 定义一个隐式值,您必须指定单例对象的类型:

    implicit val ShowType1 = new Show[Type1.type] {
      def show(a: Type1.type) = "Type1"
    }
    

    Type2 类似:

    implicit val ShowType2 = new Show[Type2.type] {
      def show(a: Type2.type) = "Type2"
    }
    

    试试吧!

    println(show(Type1))
    

    【讨论】:

    • 谢谢。那是一个错字。 Type1.type 是我一直在寻找的。关于 1 比我所拥有的更好的解决方案有什么建议吗? (即自动从基本特征中获取类型类)
    • @EugeneMi 你能澄清一下自动从基本特征获取类型类是什么意思吗?
    • @EugeneMi - 这个答案解决了你的问题吗?
    • - 是的,但仍在尝试找到更好的方法来完成 2(请参阅更新的问题)
    • 为了澄清(2),当存在任何特征、类或对象扩展 MyType 且与类型类无关时,您是否希望在编译时得到错误?
    猜你喜欢
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    相关资源
    最近更新 更多