2013-08-23 49 views
0

我正在学习Scalaz 7,类型类系统太抽象了,有一件我不明白的就是为什么Bind.ap是以这样的方式由bind实现的。为什么Bind.ap是通过Bind.bind在Scalaz中实现的7

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]

回答

3

我知道我们可以对待F[A => B]作为F[C]

所以CA => B。我们称之为事实1

让我们改写bind具有与d C和B代替A,所以我们不要被碰撞类型参数变量困惑:

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

所以f论点的bind第二个参数列表中有为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
  • faF[A]型的,也就是在ap第一个参数列表中fa - 不绑定
  • 综观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))) 
+0

谢谢,这真的很有帮助。最容易混淆的部分是'bind(f)(f => map(fa)(f))'的第二个参数的名称,应该改为'bind(f)(g => map(fa) )' – smilingleo

1

正如您从bind方法签名中可以看到的,这只是一个自命名的Haskell命名方式flatMap函数。所以Bind特征为Monad提供了必要的flatMap

也许会更容易理解,如果我们采取List[Int => String],而不是F[A => B],还等什么bind做它从列表中的每个功能,让我们说我们有以下列表:List((x: Int) => (x + 1).toString)f参数和List(1,2)fa参数ap方法,并将f自变量(ListInt => String函数)的每个函数应用于参数fa的每个值(ListInt)。

所以上答案如何为f =>地图(FA)(F)相当于A => F [B]A在这个代码是从fList一个Int => String功能,当你映射来自一些值faListF[B],这将是类型String

相关问题