2016-10-06 2 views
0

Я хотел бы сделать что-то вроде следующего:Как использовать переменную как параметр типа Scala?

val aoeu = List((0, 1), (0, 1, 2)) 
List(Tuple2, Tuple3).foreach { snth => 
    println(aoeu.filter(_.isInstanceOf[snth]).map(_.asInstanceOf[snth])) 
} 

Возможно ли это?

+0

Да, но он становится сложным и нарушает безопасность типа компиляции. См. Https://medium.com/@sinisalouc/overcoming-type-erasure-in-scala-8f2422070d20#.8ohbqsjqg – spiffman

+0

В Scala легко передать тип и вернуть значение, используя implicits; но гораздо сложнее (и небезопасно) передавать значение и возвращать тип. В вашем примере это может работать в основном, если вы замените 'val snth = Product' на' type snth = Product', за исключением ошибки времени выполнения, потому что вы используете 'Boolean' для' Product'. Какова ваша фактическая цель? – Yawar

+0

Как @Yawar указал после того, как вы изменили на 'type snth = Product',' aoeu.isInstanceOf [snth] 'является логическим и, следовательно, вы не можете использовать его как экземпляр' snth' –

ответ

0

Как я уже упоминал, в Scala это довольно удобно и (относительно) легко передать параметр типа и вернуть значение. То, что сложно, а не скомпилировано, безопасно, идет другим путем. На ваш вопрос, как он есть, ответ ... любопытный. То, что мы можем сделать, - это определить класс типа, который позволит понять идею безопасного преобразования, настроить некоторые экземпляры для интересующих нас типов и затем выполнить наши операции. Итак, вот что у меня есть:

import scala.util.Try 

/** 
A typeclass to represent safe casting behaviour. 
*/ 
trait HasInstance[A] { def apply(any: Any): Option[A] } 

object HasInstance { 
    /** 
    A helper to quickly create a typeclass instance. 
    */ 
    private class Impl[A](_apply: Any => Option[A]) 
    extends HasInstance[A] { 
    override def apply(any: Any): Option[A] = _apply(any) 
    } 

    /* Instances for standard types. */ 

    implicit val int: HasInstance[Int] = 
    new Impl(any => Try(any.asInstanceOf[Int]).toOption) 

    implicit def tuple2[A, B]: HasInstance[Tuple2[A, B]] = 
    new Impl(any => Try(any.asInstanceOf[Tuple2[A, B]]).toOption) 

    implicit def tuple3[A, B, C]: HasInstance[Tuple3[A, B, C]] = 
    new Impl(any => Try(any.asInstanceOf[Tuple3[A, B, C]]).toOption) 
} 

object Test { 
    def test(): Unit = { 
    val xs = List((0, 1), (0, 1, 2)) 

    // Flatmap will automatically filter out `None` values. 

    println(xs flatMap implicitly[HasInstance[Tuple2[Int, Int]]].apply) 
    // ==> List((0, 1)) 

    println(
     xs flatMap implicitly[HasInstance[Tuple3[Int, Int, Int]]].apply) 
    // ==> List((0, 1, 2)) 
    } 
} 

Обратите внимание, что мы до сих пор не можем захватить экземпляры в список, потому что их типы вынудят Scala к базовому типу к AnyRef хранить их вместе. Если вы хотите иметь и сопоставлять гетерогенные списки, вы находитесь на безжизненной территории. На самом деле, вы можете быть в любом случае, потому что вы, вероятно, захотите сделать общий вывод, чтобы легко выводить экземпляры для HasInstance.

Смежные вопросы