Как настроить несколько границ типа ORed в Scala

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

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

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

(Аналогичный вопрос здесь)


person oluies    schedule 24.09.2010    source источник


Ответы (4)


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

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
person Daniel C. Sobral    schedule 24.09.2010
comment
@Brent Как я уже сказал по электронной почте, это, вероятно, результат ввода класса объекта в разные строки. Смотрите мою правку. - person Daniel C. Sobral; 26.09.2010

Вы могли бы немного выиграть от типа 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
person Don Mackenzie    schedule 24.09.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)}
person Landei    schedule 25.09.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/

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

person michid    schedule 24.09.2010