Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parallelism, Exercise 7.6 answers missing #584

Open
otto-dev opened this issue Mar 23, 2020 · 0 comments
Open

Parallelism, Exercise 7.6 answers missing #584

otto-dev opened this issue Mar 23, 2020 · 0 comments

Comments

@otto-dev
Copy link

otto-dev commented Mar 23, 2020

The answers for Exercise 7.6 are missing. Only parFilter is provided, but not map3 to map5, also not the reduce/fold function for summation/maximum/character count.

https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/parallelism/Par.scala

I'd like to be able to review my approach against a model approach. I'll provide my answers below if it's any help.

I've implemented map3 like this:

  def map3[A, B, C, D](a: Par[A], b: Par[B], c: Par[C])(f: (A, B, C) => D): Par[D] = {
    val pab = map2(a, b)((a, b) => f(a, b, _))
    map2(pab, c)((f, n) => f(n))
  }

With map5 I became a bit fancier and implemented a flapMap first. Then I implemented it like this:

  def map5[A, B, C, D, E, F](a: Par[A], b: Par[B], c: Par[C], d: Par[D], e: Par[E])(f: (A, B, C, D, E) => F): Par[F] = {
    val pa = map(a)(f.curried)
    val pb = flatMap(pa)(lift(_)(b))
    val pc = flatMap(pb)(lift(_)(c))
    val pd = flatMap(pc)(lift(_)(d))
    flatMap(pd)(lift(_)(e))
  }

For the other exercises I implemented a reduce and parReduce function first, like this:

  def reduce[A](as: List[A])(f: (A, A) => A): Par[A] = {
    val pars: List[Par[A]] = as.map(v => lazyUnit(v))
    parReduce(pars)(f)
  }

  def parReduce[A](as: List[Par[A]])(f: (A, A) => A): Par[A] = {
    if (as.isEmpty) throw new IllegalArgumentException("Trying to reduce list of zero elements")
    else if (as.size == 1) as.head
    else {
      val (left, right) = as.splitAt(as.size / 2)
      map2(parReduce(left)(f), parReduce(right)(f))(f)
    }
  }

And then solved the exercises like so:

  def max(ns: List[Int]): Par[Int] = reduce(ns)(math.max)

  def characters(ss: List[String]): Par[Int] = {
    val ls = ss.map(asyncF(_.length))
    parReduce(ls)(_ + _)
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants