How do I setup multiple ORed type bounds in Scala

后端 未结 4 1193
难免孤独
难免孤独 2020-12-16 18:43

Is it possible to do something like this in Scala:

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

That is,

相关标签:
4条回答
  • 2020-12-16 18:52

    You could get a little mileage from the Either type. However the Either hierarchy is sealed and handling more than two types becomes cumbersome.

    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
    
    0 讨论(0)
  • 2020-12-16 18:53

    Another solution is wrapper classes:

    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)}
    
    0 讨论(0)
  • 2020-12-16 18:57

    Not really possible as you put it, but you can do it using the type class pattern. For example, from 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)
    ^
    

    EDIT

    This works if class and object are companions. On REPL, if you type each on a different line (ie, a "result" appears between them), they are not companions. You can type it like below, though:

    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
    
    0 讨论(0)
  • 2020-12-16 19:06

    There is this hack:

    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)
    

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

    And also this question.

    0 讨论(0)
提交回复
热议问题