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

标签 scalaz

这是一个函数:(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 仅形成 ArrowString\/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/

相关文章:

sql - 使用 Postgres 枚举进行 JDBC 插入

scala - scalaz 中是否有 Try 对象的序列函数?

scala - 如何返回 EitherT 内的元组

scalaz - λ[α =>F] 是什么意思?

scala - 展平嵌套 Scalaz 验证

scalaz.Equal 用于路径依赖类型

scala - 在Scalaz中对一系列析取进行分区

scala - 为什么 getOrElse 会丢失 scalaz 中的类型推断

scala - 为什么 OptionT 不适用于 Try?