将 2 个 Eithers 与 Cats Cartesian 合并

Merging 2 Eithers with Cats Cartesian

这段代码是我写的

import cats.Cartesian
import cats.instances.option._
val x = Some(1)
val y = Some(2)
Cartesian[Option].product(x, y)

这给了我一些 ((1, 2))。好!

所以我又试了一次

import cats.Cartesian
import cats.instances.either._
val x : Either[String, Int] = Right(1)
val y : Either[String, Int] = Right(2)
Cartesian[Either].product(x, y)

现在我得到一个错误

cmd11.sc:1: Either takes two type parameters, expected: one
val res11 = Cartesian[Either].product(x, y) 

为什么我没答对((1, 2))

我找到了答案

type MyEither[A] = Either[String, A]
val x : MyEither[Int] = Right(10)
val y : MyEither[Int] = Right(20)
Cartesian[MyEither].product(x, y)
res19: MyEither[(Int, Int)] = Right((10, 20))

有点 hack,但您也可以使用结构类型以更短的方式完成此操作:

Cartesian[({type L[A] = Either[String, A]})#L].product(x, y)

编辑:在未来,看起来 Dotty 最终会带来部分类型的应用程序,所以你可以这样做 Cartesian[Either[String, _]]http://dotty.epfl.ch/docs/internals/higher-kinded-v2.html

Either 不是 CartesianEither[A, ?](给出一种类型参数)是。简单的答案就像你已经说过的那样:

type MyEither[A] = Either[String, A]
val x: MyEither[Int] = Right(10)
val y: MyEither[Int] = Right(20)
Cartesian[MyEither].product(x, y)
res0: MyEither[(Int, Int)] = Right((10, 20))

你也可以使用 lambda 类型

// A type-lambda. Scala doesn't have a nice syntax for this but it's
// analogous to a function { a => { b => either(a,b) } }.
// Variance optional
type CurriedEither[+A] = { type l[+B] = Either[A, B] }
Cartesian[CurriedEither[String]#l].product(x, y)
// Can also inline
// This is a standard approach for one-off situations
Cartesian[{type l[B] = Either[String, B]}#l].product(x, y)

如果您有 kind-projector 插件,您可以编写

Cartesian[Either[String, ?]].product(x, y)

基本上,它为 lambda 提供了一个很好的语法。