2014-06-19 30 views
0

我有一个保持了与值相关联的元数据的容器类型Scala的隐式转换。,并不适用于某些类型的

class Container[A](val value: Option[A], val meta: Metadata) 

有时是非常有用的访问元,但大部分的时间,更方便与价值的工作,如果它是Option[A]。这有一个隐式转换。

object Container { 
    implicit def containerToValue[A](c: Container[A]): Option[A] = c.value 
} 

所有这些工作正常。问题是,往往会有一个转换目前从A => B隐含的价值恰好是Container[A]。我期望做的是提供一种基本从Container[A] => Option[B]进行隐式转换的方法。我第一次尝试的东西的影响:

object Container { 
    implicit def containerToValue[A](c: Container[A]): Option[A] = c.value 
    implicit def containerToB[A,B](c: Container[A])(implicit conv: (A) => B): Option[B] = c.value.map(conv) 
} 

斯卡拉不喜欢,在所有的,所以作为备用,因为在90%的病例B实际上是一个String,我试着做一些更填写的类型:

object Container { 
    implicit def containerToValue[A](c: Container[A]): Option[A] = c.value 
    implicit def containerToB[A](c: Container[A])(implicit conv: (A) => String): Option[String] = c.value.map(conv) 
} 

这样做的好一点,但我得到了一些关于模糊性的错误。我在想,如果有一种方法来指定AString是。也许像这样:

implicit def containerToB[A >!> String] 

这样我可以告诉编译器这种隐式转换只适用于当A不是字符串。

有没有更好的方法来处理这个问题?

+1

我知道这可能不是你想听到的,但请重新隐像这样的转换是可怕的东西,几乎肯定更好的方式来获得你正在寻找的便利。 –

回答

1

而不是做一个隐式转换(因为它们是难以调试,在你最意想不到的事业运行时错误他们,使代码一般不太清楚),为什么不是一个类型的类加进来,这样就可以正常工作用你想要与他们一起工作的方式?

trait Extractor[A,B]{ 
    def opt(that: Container[A]): B 
} 

,然后你明确地创建所有你可能希望有不同的情况:

def myGloriousFunction[B](that: Container[A])(implicit ex: Extractor[A,B]) ={ 
    val value = ex.opt(that) 
    //more stuff 
} 

它会处理“提取”的发现你的内心Option,它仍然相当明确在其签名中。

相关问题