Как настроить несколько границ типа ORed в Scala - PullRequest
9 голосов
/ 25 сентября 2010

Можно ли сделать что-то подобное в Scala :

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

То есть тип A может быть String или Int. Возможно ли это?

(Подобный вопрос здесь )

Ответы [ 5 ]

11 голосов
/ 25 сентября 2010

Не совсем возможно, как вы говорите, но вы можете сделать это, используя шаблон класса type. Например, с здесь :

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

Это работает, если класс и объект являются компаньонами. На 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
5 голосов
/ 25 сентября 2010

Вы можете получить небольшой пробег от любого типа. Однако иерархия 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 голосов
/ 25 сентября 2010
2 голосов
/ 25 сентября 2010

Другое решение - классы-обёртки:

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)}
1 голос
/ 25 сентября 2010

Есть этот хак:

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/

А также этот вопрос .

...