L型在A型中处于逆变位置=>要么[L, B] [英] Type L is in contravariant position in type A => Either[L, B]

查看:43
本文介绍了L型在A型中处于逆变位置=>要么[L, B]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试为任何一个编写 flatMap 的简单实现

I tried to write simple implementation of flatMap for Either

sealed trait Either[+L, +R] {
  def flatMap[B](f: R => Either[L, B]): Either[L, B] = this match {
    case Left(e) => Left(e)
    case Right(e) => f(e)
  }
}

final case class Right[+A, +B](right: B) extends Either[A, B]
final case class Left[+A, +B](left: A) extends Either[A, B]

并面临以下问题:协变类型 L 在类型 f 中处于逆变位置:R => 值 f 的任一 [L,B],但为什么会这样?当我们将变体类型作为函数的参数时,我认为我们的类型处于逆变位置,它与类型声明无关

and faced following problem: covariant type L is in contravariant position in type f: R => Either[L, B] of value f, but why is it so? I thought that our type is in contravariant position when we take variant type as an argument for function and it has nothing to do with a type declaration

推荐答案

你可以想到 R =>[L, B] 作为L 类型的广义值" - 它与 L 不完全相同,但给定了 R它可能产生一个L.因此,您的 flatMap 使用 L 类型的广义值".同时,您的方差声明声称 Either[+L, +R]L 中是协变的,因此,Either[VerySpecial, R] 必须是 Either[RatherGeneral, R] 的特例.但这是不可能的,因为只能使用 VerySpecial 值的 flatMap 会阻塞 RatherGeneral 输入.

You can think of R => Either[L, B] as a "generalized value of type L" - it's not exactly the same thing as an L, but given an R it might produce an L. So, your flatMap "consumes generalized values of type L". At the same time, your variance declaration claims that Either[+L, +R] is covariant in L, therefore, an Either[VerySpecial, R] would have to be a special case of Either[RatherGeneral, R]. But this is impossible, because the flatMap that can consume only VerySpecial values would choke on a RatherGeneral input.

  • Either[+L, +R] 中,L 处于协变位置(它 产生" Ls,在至少有时)
  • R =>[L, B], L 仍然处于协变位置(因为函数产生Either[L, B],而Either[L, B] 依次产生 Ls,所以整个事情产生 Ls)
  • (R =>Either[L, B]) =>要么[L, B],第一个L出现在contra变体位置,因为参数部分被方法消耗flatMap.
  • In Either[+L, +R], L is in covariant position (it "produces" Ls, at least sometimes)
  • In R => Either[L, B], L is still in covariant position (because the function produces Either[L, B], and Either[L, B] in turn produces Ls, so the whole thing produces Ls)
  • In (R => Either[L, B]) => Either[L, B], the first L appears in contravariant position, because the argument part is consumed by the method flatMap.

使用标准的下限技巧很容易解决这个问题:

This is easily fixed with the standard lower-type-bounds trick:

sealed trait Either[+L, +R] {
  def flatMap[B, M >: L](f: R => Either[M, B]): Either[M, B] = this match {
    case Left(e) => Left(e)
    case Right(e) => f(e)
  }
}

final case class Right[+A, +B](right: B) extends Either[A, B]
final case class Left[+A, +B](left: A) extends Either[A, B]

这篇关于L型在A型中处于逆变位置=>要么[L, B]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆