加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

解释scalaz-7中的Traverse [List]实现

发布时间:2020-12-16 08:49:53 所属栏目:安全 来源:网络整理
导读:我试图理解 scalaz-seven中的traverseImpl实现: def traverseImpl[F[_],A,B](l: List[A])(f: A = F[B])(implicit F: Applicative[F]) = { DList.fromList(l).foldr(F.point(List[B]())) { (a,fbs) = F.map2(f(a),fbs)(_ :: _) }} 有人可以解释List如何与App
我试图理解 scalaz-seven中的traverseImpl实现:

def traverseImpl[F[_],A,B](l: List[A])(f: A => F[B])(implicit F: Applicative[F]) = {
  DList.fromList(l).foldr(F.point(List[B]())) {
     (a,fbs) => F.map2(f(a),fbs)(_ :: _)
  }
}

有人可以解释List如何与Applicative交互?最后,我希望能够为Traverse实现其他实例.

解决方法

应用程序允许您将上下文中的函数应用于上下文中的值.因此,例如,您可以将一些((i:Int)=> i 1)应用于某些(3)并获得一些(4).我们暂时忘记这一点.我稍后再说.

List有两个表示,它是Nil或head :: tail.您可能习惯使用foldLeft折叠它,但还有另一种方法可以折叠它:

def foldr[A,B](l: List[A],acc0: B,f: (A,B) => B): B = l match {
   case Nil => acc0
   case x :: xs => f(x,foldr(xs,acc0,f))
}

给定List(1,2),我们将从右侧开始应用函数的列表折叠 – 即使我们真的从左侧解构列表!

f(1,f(2,Nil))

这可用于计算列表的长度.给定清单(1,2):

foldr(List(1,(i: Int,acc: Int) => 1 + acc)
// returns 2

这也可以用于创建另一个列表:

foldr[Int,List[Int]](List(1,List[Int](),_ :: _)
//List[Int] = List(1,2)

因此,给定一个空列表和:: function,我们可以创建另一个列表.如果我们的元素在某些情况下怎么办?如果我们的上下文是一个应用程序,那么我们仍然可以在该上下文中应用我们的元素和::.继续列表(1,2)和选项作为我们的应用程序.我们从一些(List [Int]()))开始,我们想在Option上下文中应用:: function.这就是F.map2的作用.它在Option上下文中需要两个值,将两个参数的提供函数放入Option上下文并将它们一起应用.

所以在上下文之外我们有(2,Nil)=> 2 ::无

在上下文中,我们有:(一些(2),一些(无))=>一些(2 ::零)

回到最初的问题:

// do a foldr 
DList.fromList(l).foldr(F.point(List[B]())) {
  // starting with an empty list in its applicative context F.point(List[B]())
  (a,fbs)(_ :: _)
  // Apply the `::` function to the two values in the context
}

我不确定为什么使用差异DList.我所看到的是,它使用蹦床,所以希望这使得这个实现工作而不会吹嘘堆栈,但我没有尝试过,所以我不知道.

关于如此实现正确折叠的有趣部分是,我认为它为您提供了一种使用catamorphisms实现代数数据类型遍历的方法.

例如给出:

trait Tree[+A]
object Leaf extends Tree[Nothing]
case class Node[A](a: A,left: Tree[A],right: Tree[A]) extends Tree[A]

折叠将被定义为这样(它实际上遵循与List相同的方法):

def fold[A,B](tree: Tree[A],valueForLeaf: B,functionForNode: (A,B,B) => B): B = {
  tree match {
    case Leaf => valueForLeaf
    case Node(a,left,right) => functionForNode(a,fold(left,valueForLeaf,functionForNode),fold(right,functionForNode)
      )
  }
}

并且遍历将使用F.point(Leaf)的折叠并将其应用于Node.apply.虽然没有F.map3所以它可能有点麻烦.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读