【问题标题】:How do I setup multiple ORed type bounds in Scala如何在 Scala 中设置多个 ORed 类型边界
【发布时间】:2010-09-24 21:05:39
【问题描述】:

有没有可能在Scala做这样的事情:

class MyTest {
   def foo[A <: String _or_ A <: Int](p:List[A]) =  {} 
}

也就是说,A 类型可以是StringInt。这可能吗?

(类似问题here

【问题讨论】:

    标签: scala generics type-bounds


    【解决方案1】:

    你说的不太可能,但你可以使用类型类模式来做到这一点。比如来自here

    sealed abstract class Acceptable[T]
    object Acceptable {
      implicit object IntOk extends Acceptable[Int]
      implicit object LongOk extends Acceptable[Long]
    }
    
    def f[T: Acceptable](t: T) = t
    
    scala> f(1)
    res0: Int = 1
    
    scala> f(1L)
    res1: Long = 1
    
    scala> f(1.0)
    <console>:8: error: could not find implicit value for parameter ev: Acceptable[Double]
    f(1.0)
    ^
    

    编辑

    如果类和对象是伴生的,则此方法有效。在 REPL 上,如果您在不同的行上键入每个(即,它们之间出现“结果”),则它们不是同伴。不过,您可以像下面这样输入:

    scala> sealed abstract class Acceptable[T]; object Acceptable {
         |   implicit object IntOk extends Acceptable[Int]
         |   implicit object LongOk extends Acceptable[Long]
         | }
    defined class Acceptable
    defined module Acceptable
    

    【讨论】:

    • @Brent 正如我在电子邮件中所说的,这可能是由于在不同的行上键入对象的类的结果。查看我的编辑。
    【解决方案2】:

    您可以从 Either 类型中获得一点好处。然而,Either 层次结构是密封的,处理两种以上的类型变得很麻烦。

    scala> implicit def string2either(s: String) = Left(s)
    string2either: (s: String)Left[String,Nothing]
    
    scala> implicit def int2either(i: Int) = Right(i)
    int2either: (i: Int)Right[Nothing,Int]
    
    scala> type SorI = Either[String, Int]
    defined type alias SorI
    
    scala> def foo(a: SorI) {a match {
         |     case Left(v)  => println("Got a "+v)
         |     case Right(v) => println("Got a "+v)
         |   }
         | }
    foo: (a: SorI)Unit
    
    scala> def bar(a: List[SorI]) {
         |   a foreach foo
         | }
    bar: (a: List[SorI])Unit
    
    scala>
    
    scala> foo("Hello")
    Got a Hello
    
    scala> foo(10)
    Got a 10
    
    scala> bar(List(99, "beer"))
    Got a 99
    Got a beer
    

    【讨论】:

      【解决方案3】:

      另一种解决方案是包装类:

      case class IntList(l:List[Int])
      case class StringList(l:List[String])
      
      implicit def li2il(l:List[Int]) = IntList(l)
      implicit def ls2sl(l:List[String]) = StringList(l)
      
      def foo(list:IntList) =  { println("Int-List " + list.l)}
      def foo(list:StringList) =  { println("String-List " + list.l)}
      

      【讨论】:

        【解决方案4】:

        有这个黑客:

        implicit val x: Int = 0
        def foo(a: List[Int])(implicit ignore: Int) { }
        
        implicit val y = ""
        def foo(a: List[String])(implicit ignore: String) { }
        
        foo(1::2::Nil)
        foo("a"::"b"::Nil)
        

        http://michid.wordpress.com/2010/06/14/working-around-type-erasure-ambiguities-scala/

        还有这个question

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-14
          • 2013-12-25
          • 1970-01-01
          • 2021-01-24
          • 2020-07-22
          相关资源
          最近更新 更多