提升类Kleisli函数以将monadic值作为参数

时间:2013-12-16 18:03:31

标签: scala monads scalaz kleisli

我正在为我的域模型编写ScalaCheck生成器。为了增加灵活性,我的生成器返回函数为关联采用特定值。例如:

case class A(...)
case class B(...)
case class C(a: A, ...)
case class D(b: B, c: C, ...)

val genA: Gen[A] = ???
val genB: Gen[B] = ???
val genC: (A) => Gen[C] = ???
val genD: (B, C) => Gen[D] = ???

这样,我可以选择生成与特定C关联的任意A。但是,我通常不关心与模型相关联的内容:我想生成C与任何A。在这种情况下,我可以做其中一个:

for {
  a <- genA
  c <- genC(a)
} yield c

// Or, desugared and simplified:
genA flatMap genC

// Or, with a Scalaz Monad for Gen
genA >>= genC
Kleisli(genC) =<< genA

我喜欢后面的选项,因为我可以将它们包含在更复杂的表达式中而不需要相对繁琐的for循环。但是,对于像D这样不止一个参数的情况,我无法提出任何简单的解决方案。好像我被for

困住了
for {
  a <- genA
  b <- genB
  c <- genC(a)
  d <- genD(b, c)
} yield d

底线

如果有一些干净的语法可以解除不仅f: T => M[R]这样的Kleisli箭头,而且还有一个像 n <的“类似Kleisli”的函数,我将非常感激。 / em>参数g: (T, U) => M[R],关于monadic值f2: M[T] => M[R]g2: (M[T], M[U]) => M[R]的函数。像这样:

// liftX is a hypothetical lifting method enriched onto Function1-N:
genD.liftX(genB, genC.liftX(genA))

我喜欢这种假设的方法是:

  • 看起来类似于未提升的函数应用程序,只需使用liftX拼接
  • 很容易构成一个复杂的表达式(请参阅解除genC内的genD

我可以写它,但在广阔的Scalaz世界中存在这样的事情吗?如果我讨论我的多参数函数会有帮助吗? Arrow组合者会帮忙吗?我已经浏览了Scalaz一段时间并没有提出类似的东西,但我想我会问,以防有人遇到过这种情况。

0 个答案:

没有答案