作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试编写一个通用方法来包装任何具有 scalaz.IsEmpty
的东西typeclass 实例到 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
和更高类型的方法?
最佳答案
scala> asOption0(List(1,2,3))
<console>:17: error: could not find implicit value for parameter
ev: scalaz.IsEmpty[[A]List[Int]]
此错误告诉您它找不到列表的 IsEmpty
实例,这是因为类型参数无关紧要。 Scalaz 对任何列表都有一个隐式,无论类型参数如何。
该方法请求一个 IsEmpty[List[Int]]
,而 Scalaz 只有一个可用于 IsEmpty[List[_]]
。由于 IsEmpty
不关心列表的内容,我们只是通过提供更详细的 IsEmpty
版本来使 asOption0
方法满意:
def asOption0[C](c: C)(implicit ev: IsEmpty[({ type B[_] = C })#B]) =
if (ev.isEmpty(c)) None else Some(c)
implicit def detailedIsEmpty[A, C[_]](implicit ev: IsEmpty[C]) =
ev.asInstanceOf[IsEmpty[({ type B[_] = C[A] })#B]]
asOption0("test") //> res0: Option[String] = Some(test)
asOption0(List(1, 2, 3)) //> res1: Option[List[Int]] = Some(List(1, 2, 3))
asOption0("") //> res2: Option[String] = None
asOption0(List[Int]()) //> res3: Option[List[Int]] = None
我重新审视了这个问题,找到了一个看起来更简洁的解决方案。我担心这不是 OP 想要的结果。
trait IsEmptyLike[F] {
def isEmpty(fa: F): Boolean
}
object IsEmptyLike {
implicit def case0[A](implicit ev: IsEmpty[({ type B[_] = A })#B]) =
new IsEmptyLike[A] {
def isEmpty(fa: A): Boolean = ev.isEmpty(fa)
}
implicit def case1[A[_], B](implicit ev: IsEmpty[A]) =
new IsEmptyLike[A[B]] {
def isEmpty(fa: A[B]): Boolean = ev.isEmpty(fa)
}
implicit def case2[A[_, _], B, C](implicit ev: IsEmpty[({ type D[X] = A[B, X] })#D]) =
new IsEmptyLike[A[B, C]] {
def isEmpty(fa: A[B, C]): Boolean = ev.isEmpty(fa)
}
}
def asOption[C](c: C)(implicit ev: IsEmptyLike[C]) =
if (ev.isEmpty(c)) None else Some(c)
关于scala - 如何为泛型类型编写 scalaz.IsEmpty 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14924707/
我是一名优秀的程序员,十分优秀!