0

我正在研究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 A => F[B],如何f => map(fa)(f)等效于A => F[B]??

4

2 回答 2

3

我知道我们可以F[A => B]F[C]

C也是如此A => B。让我们称这个事实为 1

让我们用 C 替换 A 和用 D 替换 B 来重写bind,这样我们就不会被类型参数变量的冲突混淆:

def bind[C, D](fc: F[C])(f: C => F[D]): F[D]

所以f第二个参数列表中的参数bind必须是 type C => F[D],可以写(A => B) => F[D](使用fact 1)。请注意,它是偷偷摸摸的 in 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],即在-not bindfa的第一个参数列表中ap
  • 查看map的定义,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-23T07:18:11.490 回答
1

bind方法签名中可以看出,它只是一种自命不凡的 Haskell 命名flatMap函数的方式。所以BindtraitflatMapMonad.

List[Int => String]如果我们取而不是 ,也许会更容易理解F[A => B],所以bind它从列表中获取每个函数,假设我们有以下列表:List((x: Int) => (x + 1).toString)作为f参数和List(1,2)作为方法的fa参数,并从参数 (的函数中ap应用每个函数) 到参数 ( of )的每个值。fListInt => StringfaListInt

因此,关于 f => map (fa)(f)如何等效于 A => F[B]的答案,A在此代码中是一个Int => String函数f Listfa ListF[B]String

于 2013-08-23T06:16:15.927 回答