微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有任一类型的 Scala 类型参数

如何解决带有任一类型的 Scala 类型参数

class OptionLikeMatcher[F[_],T,U](typeName: String,toOption: F[T] => Option[U]) extends Matcher[F[T]] { ... }
case class RightMatcher[T]() extends OptionLikeMatcher[({type l[a]=Either[_,a]})#l,T]("Right",(_:Either[Any,T]).right.toOption)
case class LeftMatcher[T]() extends OptionLikeMatcher[({type l[a]=Either[a,_]})#l,T]("Left",(_:Either[T,Any]).left.toOption)

有人可以解释他们在这里试图用类型参数实现什么吗? toOption: F[T] => Option[U] 参数在用于 RightMatcherLeftMatcher 时具有什么类型?

它来自 Scala Specs2 库。

解决方法

让我们首先解决这里最复杂的类型构造函数:

({type l[a]=Either[_,a]})#l

是对类型 lambdas 进行编码的原始方式。可以更简洁地写成

Either[_,?]

with kind-projector,or as

[X] =>> Either[_,X]

在 Scala 3 中,它基本上只是选择 Either 的右侧参数作为相关参数,并用通配符替换左侧参数。


现在,OptionLikeMatcher 的三个类型参数是:

  • F[_] - 被匹配事物的类型构造器;预计它的行为与 Option “有点相似”,即应该有某种方法可以从中获得 Option
  • T 是插入到 F 类型构造函数中的类型; F[T] 一起给出了匹配的类型。
  • U 可以被认为是 T 的“轻微扰动”版本;它捕获的信息与 T 基本相同,但在将 F[T] 转换为 Option[U] 时允许一些受控的草率(否则,如果需要 F[T] => Option[T],那实际上与要求称为自然变换 F ~> Option 的相当严格的结构相同,在这种情况下可能过于严格)。

将它们放在一起得到 RightMatcher

  • F[A] = Either[_,A] - 即选择 Either 的右侧参数,忽略左侧参数
  • 来自 TOptionLikeMatcher 绑定到来自 TRightMatcher
  • U 中的 OptionLikeMatcher 也绑定到 T 中的 RightMatcher,即此处不使用“轻微扰乱”T 的可能性, T 中的 UOptionLikeMatcher 均由相同类型实例化。

因此,toOption 中的 RightMatcher 具有 Either[_,T] => Option[T] 类型。 (_:Either[Any,T]).right.toOption符合Either[_,T] => Option[T],因为Any出现在Either内的协变位置,而Either[Any,T]出现在函数类型内的逆变位置,所以Either[Any,T] => Option[T]Either[_,T] => Option[T] 的子类型,因为它的输入类型更加宽松,可以在需要 Either[_,T] => Option[T] 的任何地方使用。


说了这么多,我找不到任何 F 形状不是 F[T] 的应用程序(既不在 OptionLikeMatcher 中,也不在 OptionLikeChekedMatcher 中),所以似乎他们将输入类型拆分为类型构造函数 F 和类型参数 T,只是为了稍后将它们用作不可分割的单元 F[T]。也许这是从一些更复杂的构造重构后遗留下来的。

,

当用于 toOption: F[T] => Option[U]RightMatcher 时,LeftMatcher 参数具有什么类型

也许具体的演练会有所帮助。让我们考虑将类型参数 RightMatcher[Int]() 实例化为 TInt。这给了我们

F = ({type l[a]=Either[_,a]})#l
T = Int
U = T = Int

并将上述类型实例化插入

toOption: F[T] => Option[U]

我们得到

toOption: (({type l[a]=Either[_,a]})#l)[Int] => Option[Int]

简化为

toOption: Either[_,Int] => Option[Int]

让我们再练习一次 LeftMatcher[String]()。我们有

F = ({type l[a]=Either[a,_]})#l
T = String
U = T = String

并将上述类型实例化插入

toOption: F[T] => Option[U]

我们得到

toOption: (({type l[a]=Either[a,_]})#l)[String] => Option[String]

简化为

toOption: Either[String,_] => Option[String]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。