这是一个函数:(T)=> \ / [E,C]
我可以将这种类型的函数转换为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定义。我对分裂(***)特别感兴趣,但我无法弄清楚如何使用它。它看起来好像是两个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有不同的方法。
答案 0 :(得分:4)
问题是Kleisli
仅在返回类型构造函数形成Arrow
时才形成Monad
。 String \/ A
形成一个Monad,但由于\/
是善意的*,* -> *
且Monad
需要类型* -> *
的类型构造函数,因此scala无法找到Monad
实例。如果你帮忙,通过创建一个类型* -> *
的类型别名,它将找到Monad
实例,因此会找到箭头实例:
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)
}