我正在学习Scalaz 7,类型类系统是如此抽象,我无法理解的一件事是,为什么Bind.ap是由bind以这样的方式实现的。
trait Apply[F[_]] extends Functor[F] { self =>
def ap[A,B](fa: => F[A])(f: => F[A => B]): F[B]
....
}
trait Bind[F[_]] extends Apply[F] { self =>
/** Equivalent to `join(map(fa)(f))`. */
def bind[A, B](fa: F[A])(f: A => F[B]): F[B]
override def ap[A, B](fa: => F[A])(f: => F[A => B]): F[B] = bind(f)(f => map(fa)(f))
....
}我知道我们可以把F[A => B]看作F[C],所以bind的第一个参数是有意义的,但是第二个参数需要A => F[B],f => map(fa)(f)如何等同于A => F[B] ??
发布于 2013-08-23 07:18:11
我知道我们可以把
F[A => B]当成F[C]
所以C是A => B。让我们称之为事实1。
让我们重写bind,用C替换A,用D替换B,这样就不会因为碰撞类型的参数变量而混淆了:
def bind[C, D](fc: F[C])(f: C => F[D]): F[D]因此,第二个参数列表中的f参数必须是C => F[D]类型,可以编写(A => B) => F[D] (使用事实1)。注意,在bind(f)(f => ...)中,第二个f只是一个lambda参数(碰巧是一个函数),而第一个f不是一个函数。它可能是bind(f)(fun => map(fa)(fun))写的。
f => map(fa)(f)如何等同于A => F[B]??
嗯,这不是..。f => map(fa)(f)必须输入为(A => B) => F[D]。所以
f是A => B型的fa的类型是F[A],即ap的第一个参数列表中的fa,而不是绑定。map(fa)(f)将是F[B]类型这意味着
(A => B) => F[D]
f => map(fa)(f)
(A => B) => F[B]
// D is really B所以bind(f)(f => map(fa)(f))是F[B]型的,这是ap所需要的。
也许这使我们在概念上更加清楚,这就是正在发生的事情:
def ap[A, B](m_elem: => F[A])(m_fun: => F[A => B]): F[B] =
for {
fun <- m_fun
elem <- m_elem
} yield {
fun(elem)
}
//To hammer it home, same as: m_fun.flatMap(fun => m_elem.map(elem => fun(elem)))发布于 2013-08-23 06:16:15
从bind方法签名中可以看出,这只是Haskell命名flatMap函数的一种自命不凡的方式。因此,Bind特性为Monad提供了必要的flatMap。
如果我们采用List[Int => String]而不是F[A => B],可能更容易理解,所以bind从列表中获取每个函数,假设我们有以下列表:List((x: Int) => (x + 1).toString)作为f参数,List(1,2)作为fa参数,并将Int => String函数的f参数(List >函数)中的每个函数应用到fa参数(List >的Int的每个值)。
因此,上的答案是f => map(fa)(f)等价于A => FB,在这段代码中,A是来自f List的Int => String函数,当您从fa List映射一些值时,得到F[B],它的类型为< code >D28
https://stackoverflow.com/questions/18395766
复制相似问题