Как принять несколько типов в Scala - PullRequest
1 голос
/ 06 мая 2020

У меня есть несколько перегруженных методов, которые принимают несколько типов и возвращают один и тот же тип:

def foo(x: Int): Foo = ... 
def foo(x: String): Foo = ... 
def foo(x: Boolean): Foo = ... 
def foo(x: Long): Foo = ...

Теперь я хочу определить единственный способ вызова метода, например:

def bar(x: Int | String | Boolean | Long) = foo(x)  // how to do this? 

Я могу сделать это «наивным» способом, который мне не очень нравится:

def bar(x: Any) = x match {
  case i:Int => foo(i)
  case s:String => foo(s)
  case b:Boolean => foo(b)
  case l:Long => foo(l)
  case _ => throw new Exception("Unsupported type")
}

Есть ли способ лучше, возможно, используя Scalaz или какую-нибудь другую библиотеку?

Ответы [ 2 ]

4 голосов
/ 06 мая 2020

Попробуйте тип class

trait FooDoer[T] {
  def foo(x: T): Foo
}
object FooDoer {
  implicit val int: FooDoer[Int] = (x: Int) => foo(x)
  implicit val string: FooDoer[String] = (x: String) => foo(x)
  implicit val boolean: FooDoer[Boolean] = (x: Boolean) => foo(x)
  implicit val long: FooDoer[Long] = (x: Long) => foo(x)
}

def bar[T](x: T)(implicit fooDoer: FooDoer[T]): Foo = fooDoer.foo(x)

bar(1)
bar("a")
bar(true)
bar(1L)
// bar(1.0) // doesn't compile

Также иногда может помочь следующее:

def bar[T](x: T)(implicit ev: (T =:= Int) | (T =:= String) | (T =:= Boolean) | (T =:= Long)) = ???

trait |[A, B]
trait LowPriority_| {
  implicit def a[A, B](implicit a: A): A | B = null
}
object | extends LowPriority_| {
  implicit def b[A, B](implicit b: B): A | B = null
}

Как определить «дизъюнкцию типов» (типы объединения)?

1 голос
/ 06 мая 2020

Класс типов может работать так:

trait CanFoo[T] {
  def foo(t: T): Foo
}

object CanFoo {
  implicit object intFoo extends CanFoo[Int] {
    def foo(i: Int) = Foo(i)
  }
  implicit object stringFoo extends CanFoo[String] {
    def foo(s: String) = Foo(s)
  }
  implicit object boolFoo extends CanFoo[Boolean] {
    def foo(i: Boolean) = Foo(i)
  }
  implicit object longFoo extends CanFoo[Long] {
    def foo(i: Long) = Foo(i)
  }
}

def bar[T](x: T)(implicit ev: CanFoo[T]) =
  ev.foo(x)

bar(0)
bar("hello")
bar(true)
bar(0.toLong)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...