测试2个定义的静态类型是否相等

时间:2014-10-24 18:02:39

标签: scala scalaz scalaz7 scala-2.11 type-level-computation

让我们说我想出了一个组合器:

def optional[M[_]: Applicative, A, B](fn: Kleisli[M, A, B]) =
  Kleisli[M, Option[A], Option[B]] {
    case Some(t) => fn(t).map(_.some)
    case None => Applicative[M].point(none[B])
  }

此组合程序会将Kleisli[M, A, B]映射到Kleisli[M, Option[A], Option[B]

但是,经过一段时间后,我意识到(无可否认,在#scalaz的estewei的帮助下)可以使用比Option更通用的容器,即任何有{{1}的容器。实例:

Traverse

以便def traverseKleisli[M[_]: Applicative, F[_]: Traverse, A, B](k: Kleisli[M, A, B]) = Kleisli[M, F[A], F[B]](k.traverse) 现在可以定义为:

optional

但是,我想验证至少结果类型签名是否等于def optional[M[_]: Applicative, A, B](fn: Kleisli[M, A, B]) = traverseKleisli[M, Option, A, B](fn) 的原始定义,而我可以求助于将鼠标悬停在我的IDE中的两个定义上(Ensime in my案例)并比较答案,我想要一种更坚实的方法来确定答案。

我试过了:

optional

但是(很明显?)由于implicitly[optional1.type =:= optional2.type] 认为两者都被认为不稳定而失败了。

除了可能暂时使用scalac方法临时生成两个函数object之外,是否有任何简单的方法来比较它们的静态类型而不依赖于IDE演示编译器的提示?

P.S。名称apply来自于我使用该组合子作为validation DSL的一部分来获取optional - 包裹Kleisli并将其转换为Validation[String, T]的事实-wrapped Kleisli验证可选值的有效性(如果存在)。

1 个答案:

答案 0 :(得分:1)

您遇到的问题是方法不是scala中的值,并且值是单一型的。你可以测试一个特定的"实例"你的方法有正确的类型(使用无形的实用函数):

val optional1Fix = optional1[Future, Int, String] _
val optional2Fix = optional2[Future, Int, String] _
import shapeless.test._
sameTyped(optional1Fix)(optional2Fix)

但与单元测试一样,这有点令人不满意,因为即使我们测试了几个实例,我们也无法确定它是否适用于所有情况。 (注意implicitly[optional1Fix.type =:= optional2Fix.type]仍然无法工作,我假设因为编译器永远不会实现两个路径相关类型相等的时间。)

对于完整的解决方案,我们必须将完整的函数视为一个值,因此我们必须使用object替换它,并使用apply方法替换它(类似于无形' ~>)。我能想到的唯一选择是一个宏,它必须应用于包含方法的对象,并知道你想要比较哪些方法;为这个特定的测试编写一个特定的宏似乎有点过分。