lucproglangcourse / lucproglangcourse.github.io

Lecture notes for COMP 371/471: Programming languages course at Loyola University Chicago with a focus on functional languages and projects mostly in Scala
MIT License
1 stars 1 forks source link

add Fibonacci and Sieve of Erasthosthenes examples in appropriate places #31

Open klaeufer opened 7 months ago

klaeufer commented 7 months ago

Start with imperative, then naive, inefficient recursive version, then introduce accumulator.

scala> @scala.annotation.tailrec def fib(k: Int, i: Int = 0, m: BigInt = 0, n: BigInt = 1): BigInt =
     |   if (i >= k) m else fib(k, i + 1, n, m + n)

Efficient but doesn't memoize!

and/or

def facFrom(n: Int, r: BigInt): LazyList[BigInt] = n #:: facFrom(n + 1, n * r)

def fibFrom(a: BigInt, b: BigInt): LazyList[BigInt] = a #:: fibFrom(b, a + b)

Also implement nonrecursively using iterate!

val fib = LazyList.iterate((BigInt(0), BigInt(1)))((m, n) => (n, m + n)).map(_._1)

Do something similar for the sieve (corecursion)!

scala> def era(ns: Iterator[Int]): (Int, Iterator[Int]) =
     |   val p = ns.next
     |   (p, ns.filter(_ % p != 0))

val primes = Iterator.iterate(0, Iterator.from(2))((p, ns) => era(ns)).drop(1)

primes.next

TODO express as LazyList

Seq.unfold is the equivalent to Iterator.iterate for building finite structures; both can be considered anamorphisms.

Then add F-algebraic versions based on Droste examples and reference below.

Reference: https://bartoszmilewski.com/2017/02/28/f-algebras/