【发布时间】:2013-02-17 18:46:31
【问题描述】:
我正在尝试编写一个通用方法,它将具有scalaz.IsEmpty 类型类实例的任何内容包装到Option 中。它应该为空值返回None,如果它是非空的,则将其包装到Some。到目前为止,这是我想出的:
import scalaz._
import Scalaz._
def asOption0[C](c: C)(implicit ev: IsEmpty[({ type B[A] = C })#B]) =
if (ev.isEmpty(c)) None else Some(c)
def asOption1[A, C[_]](c: C[A])(implicit ev: IsEmpty[C]) =
if (ev.isEmpty(c)) None else Some(c)
asOption0 适用于 String 之类的原始类型(通过使用 type lambda 来表示 C 的形状为 B[_])和 asOption1 适用于具有一元类型构造函数的类型,例如 List :
scala> asOption0("")
res1: Option[String] = None
scala> asOption1(List(1,2,3))
res0: Option[List[Int]] = Some(List(1, 2, 3))
scala> asOption0(List(1,2,3))
<console>:17: error: could not find implicit value for parameter
ev: scalaz.IsEmpty[[A]List[Int]]
scala> asOption1("hello")
<console>:17: error: could not find implicit value for parameter
ev: scalaz.IsEmpty[Comparable]
是否可以编写一种同时适用于String、List 和更高类型的方法?
【问题讨论】:
-
我看到你改变了你的问题。你能解释一下你到底想达到什么目标吗?
-
@EECOLOR 我更改了标题以更好地匹配我问题的最后一句。我想要一个适用于任何类型的解决方案,不仅适用于
*和* -> *。另一个“显式”隐式转换似乎是必要的,例如Map不满意。我确实觉得只需提供适当的类型类实例就足以使用asOption。抱歉之前的误导性标题! -
我编辑了我的答案以添加另一个解决方案。然而,这可能仍然不是您想要的。如果不是,您能否尝试解释一下您在在寻找什么?
-
@EECOLOR 似乎我通过使用
scalaz.Unapply找到了我的问题的一个答案。此解决方案不需要任何额外的隐式转换,只需要IsEmpty的一个实例。
标签: scala generics typeclass scalaz higher-kinded-types