0

我需要从 monad 中提取函数,这对于任何 monad 都是可能的:

 def extractf[A, B, F[_]: Monad](ff: F[A ⇒ F[B]]): A ⇒ F[B] = a ⇒ {
    Monad[F].bind(ff)(f ⇒ f(a))
  }

我在 scalaz 和 hoogle 中都找不到这样的功能。

我试图在 Kleisli 上使用排序(这个想法是做 sequence . join )或 unlifting 来达到同样的效果,但这变得过于复杂,所以我停止了。

我的问题是 - 我只是找不到这个功能还是没有人出于任何原因使用它(如果是,那么如何实现相同的目标)?

谢谢!

4

1 回答 1

0
import scalaz.{Monad, Applicative, Apply, Bind}
import language.higherKinds

def extractF[A, B, F[_]: Monad](ff: F[A => F[B]]): A => F[B] =
  (Applicative[F].pure[A] _).andThen(Apply[F].apF(ff)).andThen(Bind[F].join)(_)

import scalaz.std.list._
val f = extractF(List((x: Int) => List(x, x)))
f(3) // List(3, 3)

Applicative 的纯粹是引导链,将 A 提升到 F[A] 就像 Haskell 的回归一样。然后我们使用Applicative 的弱化变体Apply 中的apF 将参数替换为函子内的函数,从F[A] 和F[A => F[B]] 获得F[F[B]]。最后,从 Bind 类型类(monad 的第二个组件)连接,将 F[F[B]] 展平为 F[B]。剩下的就是在 A 的值上调用组合函数。注意 Monad 确实是 Applicative 和 Bind,Applicative 也是 Apply,所以可以用 Monad 替换所有细粒度类型类的使用。

虽然这样可行,但在某些情况下可能会因为语法怪癖而带来不便。用户被迫将 monad 的实例显式传递给从上下文绑定或将函数保存到 val 中生成的隐式参数,然后再将其应用于参数。等效功能是:

import scalaz.{Monad, Applicative, Apply, Bind}
import language.higherKinds

def extractF[A, B, F[_]: Monad](ff: F[A => F[B]])(a: A): F[B] =
  (Applicative[F].pure[A] _).andThen(Apply[F].apF(ff)).andThen(Bind[F].join)(a)

import scalaz.std.list._
extract(List((x: Int) => List(x, x)))(3) // List(3, 3)
于 2017-04-11T20:07:53.303 回答