From 50ba59a7598adfc6b419b0a56e18c72572154e3c Mon Sep 17 00:00:00 2001 From: Stew O'Connor Date: Sat, 23 Jan 2016 08:31:53 -0800 Subject: [PATCH 1/2] add more examples to foldable.md --- docs/src/main/tut/foldable.md | 40 ++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/docs/src/main/tut/foldable.md b/docs/src/main/tut/foldable.md index 34ff817440..eaf366f5f8 100644 --- a/docs/src/main/tut/foldable.md +++ b/docs/src/main/tut/foldable.md @@ -27,7 +27,7 @@ First some standard imports. ```tut:silent import cats._ -import cats.std.all._ +import cats.implicits._ ``` And examples. @@ -57,6 +57,10 @@ Foldable[List].traverse_(List("1", "2"))(parseInt) Foldable[List].traverse_(List("1", "A"))(parseInt) Foldable[List].sequence_(List(Option(1), Option(2))) Foldable[List].sequence_(List(Option(1), None)) + +val prints: Eval[Unit] = List(Eval.always(println(1)), Eval.always(println(2))).sequence_ +prints.value + Foldable[List].dropWhile_(List[Int](2,4,5,6,7))(_ % 2 == 0) Foldable[List].dropWhile_(List[Int](1,2,4,5,6,7))(_ % 2 == 0) @@ -86,5 +90,35 @@ as opposed to def foldRight[A, B](fa: F[A], z: B)(f: (A, B) => B): B ``` -which someone familiar with the `foldRight` from the collections in Scala's standard -library might expect. +which someone familiar with the `foldRight` from the collections in +Scala's standard library might expect. This will prevent operations +which are lazy in their right hand argument to traverse the entire +structure unnecessarily. For example, if you have: + +```tut +val allFalse = Stream.continually(false) +``` + +which is an infinite stream of `false` values, and if you wanted to +reduce this to a single false value using the logical and (`&&`). You +intuitively know that the result of this operation should be +`false`. It is not necessary to consider the entire stream in order to +determine this result, you only need to consider the first +value. Using `foldRight` from the standard library *will* try to +consider the entire stream, and thus will eventually cause a stack +overflow: + +```tut +try { + allFalse.foldRight(true)(_ && _) +} catch { + case e:StackOverflowError => println(e) +} +``` + +With the lazy `foldRight` on `Foldable`, the calculation terminates +after looking at only one value: + +```tut +Foldable[Stream].foldRight(allFalse, Eval.now(true))((a,b) => Eval.now(a && b.value)).value +``` From dd6a04c522eaa9d2c1a0cab1ea7bee9039739a7f Mon Sep 17 00:00:00 2001 From: Stew O'Connor Date: Sat, 30 Jan 2016 09:09:37 -0800 Subject: [PATCH 2/2] make the foldRight example more stack safe :wq --- docs/src/main/tut/foldable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/main/tut/foldable.md b/docs/src/main/tut/foldable.md index eaf366f5f8..85339420e1 100644 --- a/docs/src/main/tut/foldable.md +++ b/docs/src/main/tut/foldable.md @@ -120,5 +120,5 @@ With the lazy `foldRight` on `Foldable`, the calculation terminates after looking at only one value: ```tut -Foldable[Stream].foldRight(allFalse, Eval.now(true))((a,b) => Eval.now(a && b.value)).value +Foldable[Stream].foldRight(allFalse, Eval.True)((a,b) => if (a) b else Eval.now(false)).value ```