将2个Eithers与Cats Cartesian合并

时间:2017-07-13 00:50:38

标签: scala scala-cats

我写了这段代码

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))

3 个答案:

答案 0 :(得分:3)

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

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)

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

答案 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))

答案 2 :(得分:1)

有点破解,但您也可以使用结构类型以稍微缩短的方式完成此操作:

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