如何在2个Kleisli Arrows上使用`split`

时间:2014-10-21 04:38:00

标签: scalaz

这是一个函数:(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有不同的方法。

1 个答案:

答案 0 :(得分:4)

问题是Kleisli仅在返回类型构造函数形成Arrow时才形成MonadString \/ 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)

}