繁体   English   中英

半群类型组(Either),组合略有改变

[英]Semigroup typeclass (Either) with slightly altered combine

使用cats.Semigroup可以写这个:

import cats.Semigroup
import cats.implicits._

val l1: String Either Int = Left("error")
val r1: String Either Int = Right(1)
val r2: String Either Int = Right(2)

l1 |+| r1 // Left("error")
r1 |+| r2 // Right(3)

我希望有一个同样惯用的运算符(类似组合),其工作方式如下:

  • 如果我的计算中有(至少)一个Right ,则返回一个Right
  • 如果只有 Left s,则返回Left

例如:

Right(1) |+| Right(2) // Right(3) 
Right(1) |+| Left("2") // Right(1) 
Left("1") |+| Left("2") // Left("12") // in my particular case the wrapped value here does not really matter (could also be e.g. Left("1") or Left("2")), but I guess Left("12") would be the must logical result

有没有这样的东西已经定义在例如Either猫?

现在有很多合法的半群实例来进行Either ,以及哪些应该被包含在了猫的问题有些 争论 在这方面,Cats,Scalaz和Haskell都做出了不同的选择,你所描述的实例(翻转但是左移和右移组合)与其中三个不同,它没有我具体的名称。我知道,并没有以任何名义或任何形式由猫提供。

这当然不是问题本身,因为正如我们在下面看到的那样,验证这个实例是合法的很容易,但是你应该注意一个潜在的问题。 你并没有真正解释你想要的语义,但是如果你想将它推广到Monoid ,那么当你同时拥有一个LeftRight时你选择了Right意味着你的零必须是Left 如果您将权利视为成功和左倾作为错误在组合值时可以安全忽略,那么这可能有点奇怪。

你问的是Semigroup ,不是Monoid ,所以让我们暂时忽略它,并证明这件事是合法的。 首先是定义:

import cats.kernel.Semigroup

implicit def eitherSemigroup[A, B](implicit
  A: Semigroup[A],
  B: Semigroup[B]
): Semigroup[Either[A, B]] = Semigroup.instance {
  case (Right(x), Right(y)) => Right(B.combine(x, y))
  case (r @ Right(_), Left(_)) => r
  case (Left(_), r @ Right(_)) => r
  case (Left(x), Left(y)) => Left(A.combine(x, y))
}

然后是检查部分:

import cats.instances.int._
import cats.instances.string._
import cats.kernel.instances.either.catsStdEqForEither
import cats.kernel.laws.discipline.SemigroupTests
import org.scalacheck.Test.Parameters

SemigroupTests(eitherSemigroup[String, Int]).semigroup.all.check(Parameters.default)

是的,没关系:

+ semigroup.associative: OK, passed 100 tests.
+ semigroup.combineAllOption: OK, passed 100 tests.
+ semigroup.repeat1: OK, passed 100 tests.
+ semigroup.repeat2: OK, passed 100 tests.

就个人而言,如果我想要这样的东西,我可能会使用一个包装器,以避免混淆我的代码(包括我自己)的未来读者,但鉴于没有人真正知道Either的半群该做什么,我不认为使用自定义实例对于标准库中的大多数其他类型来说,问题是一个大问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM