美文网首页
Chapter 3: datastructures函数式数据结构

Chapter 3: datastructures函数式数据结构

作者: 胖达_4b7e | 来源:发表于2019-05-16 22:27 被阅读0次

    Scala 函数式编程 https://github.com/fpinscala/fpinscala](https://github.com/fpinscala/fpinscala)

    函数式数据结构:

    • 只能被纯函数操作?
    • 不可变, 操作只会产生新对象, 不会改变原对象
    • 不是用复制实现

    单向列表(原理像标准库中的List)

    以下都定义在 文件 List.scala 里面

    sealed trait List[+A]
    case object Nil extends List[Nothing] 
    case class Cons[+A](head: A, tail: List[A]) extends List[A]
    

    通常用trait引入数据类型, sealed表示不可在其他地方再实现List, 只能就这2个实现, 这2种形式

    • Nil 空列表, 就这么一个单例对象, 注意它继承 List[Nothing] 是所有列表的子类, 所以所有list都可以用
    • Cons 类, 由第一个元素 head 和 后续 名为tail的 List 组成 构造器入参是 (head: A, tail: List[A])

    以下 object List 是List class的伴生对象, 相当于java里的工具类

    object List {
      def sum(ints: List[Int]): Int = ints match {
        case Nil => 0 
        case Cons(x,xs) => x + sum(xs) // 递归
      }
    
      def product(ds: List[Double]): Double = ds match {
        case Nil => 1.0
        case Cons(x,xs) => x * product(xs)
      }
    
      def apply[A](as: A*): List[A] = {
        if (as.isEmpty) {
          Nil
        } else {
          Cons(as.head, apply(as.tail: _*))
        }
      }//apply end
    //....
    
    // 去掉满足f的前缀
      def dropWhile[A](l: List[A], f: A => Boolean): List[A] ={
        l match {
          case Cons(h,t) if f(h) => dropWhile(t, f)
          case _ => l
        }
      }
    }
    

    apply 函数 使List 可以List(1,4,5) 这样来方便地构造
    (as: A*)这样的可变参数, 是一个语法糖, 其实内部是 Seq[A]

    参数分组 帮助类型推导

    如上的dropWhile函数

      val xs:List[Int]=List(1,23,34,0)
      val exl=dropWhile(xs,x=>x<4)
    

    这样调用会红, 必须x:Int=>x<4 这样声明类型,因为scala不能推导x的类型是Int,
    (l: List[A], f: A => Boolean) 改成
    (l: List[A])( f: A => Boolean) 这样参数分组, 就可以帮助类型推导了

    fold

    这2个函数,

      def sum(ints: List[Int]): Int = ints match {
        case Nil => 0 
        case Cons(x,xs) => x + sum(xs) // 不同
      }
    
      def product(ds: List[Double]): Double = ds match {
        case Nil => 1.0
        case Cons(x,xs) => x * product(xs)// 不同
      }
    

    其实只有子表达式不用,可以泛化

    // 抽出来公共部分
      /**
        * 
        * @param as 原列表
        * @param z 积累的第一个值
        * @param f 
        * @tparam A 列表元素类型
        * @tparam B 返回值类型
        * @return 一个值
        */
      def foldRight[A,B](as: List[A], z: B)(f: (A, B) => B): B = // Utility functions
        as match {
          case Nil => z
          case Cons(x, xs) => f(x, foldRight(xs, z)(f))// 递归
        }
    
      def sum(ns: List[Int]) = foldRight(ns, 0)((x,y) => x + y)
    
      def product(ns: List[Double]) =  foldRight(ns, 1.0)(_ * _)
    

    注意抽出来的函数的foldRight 的返回值类是B ,list的元素类型是'A', 不一定要有关系

    ADT

    代数 数据类型

    This is a type where we specify the shape of each of the elements. Wikipedia has a thorough discussion. "Algebraic" refers to the property that an Algebraic Data Type is created by "algebraic" operations. The "algebra" here is "sums" and "products":

    • "sum" is alternation (A | B, meaning A or B but not both)
    • "product" is combination (A B, meaning A and B together)
      Sums and products can be repeatedly combined into an arbitrarily large structures.

    除了之前的 单向列表List 外, 还有树 Tree

    sealed trait Tree[+A]
    
    case class Leaf[A](value: A) extends Tree[A]
    case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]sealed trait Tree[+A]
    
    

    Branch就是 Leaf累加而来

    List 常用方法
    https://www.runoob.com/scala/scala-lists.html

    相关文章

      网友评论

          本文标题:Chapter 3: datastructures函数式数据结构

          本文链接:https://www.haomeiwen.com/subject/jopdaqtx.html