这是一个函数:(T) =>\/[E,U]
我可以将这种类型的函数转换为 Kleisli
def kleisli[E,T,U](c: T => \/[E,U]) = Kleisli[({type λ[+α] = \/[E, α]})#λ, T, U](c)
这使我能够组合和 flatMap,结合功能。
val positive = (t: Int) => if (t > 0) \/-(t) else -\/("Negative")
val even = (t: Int) => if (t % 2 == 0) \/-(t) else -\/("Odd")
val evenAndPositive = kleisli(positive) >=> kleisli(even)
好的,不错。我最近遇到了 ArrowOps 中的功能并在 KleisliArrow 中为 Kleisli 定义。我对 split (***) 特别感兴趣,但我不太清楚如何使用它。看起来好像是对两个Kleisli的操作,同>==>:
val eventAndPositive2 = kleisli(positive) *** kleisli(event)
但是,这总是失败:
error: could not find implicit value for parameter F0: scalaz.Unapply2[scalaz.Arrow,scalaz.Kleisli[[+α]scalaz.\/[String,α],Int,Int]]
val eventAndPositive2 = kleisli(positive) *** kleisli(event)
如何定义 Unapply2 或者是否有一种不同的方式来使用 split。
最佳答案
问题在于,当返回类型构造函数形成 Monad
时,Kleisli
仅形成 Arrow
。 String\/A
形成一个 Monad,但是因为 \/
是类 *,* -> *
和 Monad
需要 * -> *
类型的类型构造函数,scala 无法找到 Monad
实例。如果您帮助解决这个问题,通过创建一个类型为 * -> *
的类型别名,它将找到 Monad
实例,从而找到 Arrow 实例:
import scalaz._, Scalaz._
object Main {
type Err[A] = String\/A
def kleisli[T,U](c: T => \/[String,U]) = Kleisli[Err, T, U](c)
val positive = (t: Int) => if (t > 0) \/-(t) else -\/("Negative")
val even = (t: Int) => if (t % 2 == 0) \/-(t) else -\/("Odd")
val evenAndPositive = kleisli(positive) >=> kleisli(even)
val eventAndPositive2 = kleisli(positive) *** kleisli(even)
}
关于scalaz - 如何在 2 个 Kleisli Arrows 上使用 `split`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26478993/