2015-09-24 6 views
2

Я пытаюсь написать метод, который использует метод isEmpty по типам String, Option и List. Эти классы не имеют общую базовую черту с этим методом, поэтому я попытался передать неявный EmptyChecker с ними:Scala - как создать единый неявный, который может быть использован для конструктора типа

trait EmptyChecker[Field] { 
    def isEmpty(data: Field): Boolean 
    } 

    implicit val StringEmptyChecker: EmptyChecker[String] = new EmptyChecker[String] { 
    def isEmpty(string: String): Boolean = string.isEmpty 
    } 

    def printEmptiness[Field](field: Field)(implicit emptyChecker: EmptyChecker[Field]): Unit = { 
    if (emptyChecker.isEmpty(field)) 
     println("Empty") 
    else 
     println("Not empty") 
    } 

    printEmptiness("abc") // Works fine 

String пустой шашка прекрасно работает, но я ударил проблемы с созданием пустые шашки для конструкторов типа Option и List.

Например, Option не работает:

implicit val OptionChecker: EmptyChecker[Option[_]] = new EmptyChecker[Option[_]] { 
    def isEmpty(option: Option[_]): Boolean = option.isEmpty 
    } 

    // Both fail compilation: "could not find implicit value for parameter emptyChecker: EmptyChecker[Some[Int]] 
    printEmptiness(Some(3)) 
    printEmptiness[Option[Int]](Some(3))  

Если я использую конкретный Option[Int] шашку, он работает немного лучше, но немного уродливый:

implicit val OptionIntChecker: EmptyChecker[Option[Int]] = new EmptyChecker[Option[Int]] { 
    def isEmpty(optionInt: Option[Int]): Boolean = optionInt.isEmpty 
    } 

    // Fails like above: 
    printEmptiness(Some(3)) 

    // Passes compilation: 
    printEmptiness[Option[Int]](Some(3)) 

Так мой вопрос is: возможно ли сделать один EmptyChecker для каждого типа Option и List и заставить их работать с моим методом, не требуя явного объявления типа всякий раз, когда я его называю? Я пытаюсь получить тип безопасного утиного набора текста.

Я использую scala 2.11.6.

Заранее благодарен!

ответ

3

Источник вашей проблемы: Some(1) является Some[Int], а не Option[Int]. Есть несколько способов обойти это; вы можете явно выразить выражение с типом типа: printEmptiness(Some(3): Option[Int]). Кроме того, вы можете определить вспомогательный метод, чтобы сделать это за вас автоматически, и если вы используете Scalaz, есть один из них при условии:

import scalaz.syntax.std.option._ 
printEmptiness(3.some) 

Кроме того, если вы используете Scalaz, вы можете найти, глядя на PlusEmpty/ApplicativePlus/MonadPlus классы классов полезны.