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

Adds Show[Stream] #775

Merged
merged 1 commit into from
Jan 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions core/src/main/scala/cats/std/stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cats
package std

import scala.collection.immutable.Stream.Empty
import cats.syntax.show._

trait StreamInstances {
implicit val streamInstance: Traverse[Stream] with MonadCombine[Stream] with CoflatMap[Stream] =
Expand Down Expand Up @@ -58,6 +59,11 @@ trait StreamInstances {
override def isEmpty[A](fa: Stream[A]): Boolean = fa.isEmpty
}

implicit def streamShow[A: Show]: Show[Stream[A]] =
new Show[Stream[A]] {
def show(fa: Stream[A]): String = if(fa.isEmpty) "Stream()" else s"Stream(${fa.head.show}, ?)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the .show syntax here will result in an extra allocation for the ShowOps object, right? In this particular case that probably doesn't matter, but it may be worth having a convention of not using syntax when it comes at an allocation cost in Cats. I don't know. What do people think?

}

// TODO: eventually use algebra's instances (which will deal with
// implicit priority between Eq/PartialOrder/Order).

Expand Down
22 changes: 22 additions & 0 deletions tests/src/test/scala/cats/tests/StreamTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,26 @@ class StreamTests extends CatsSuite {

checkAll("Stream[Int] with Option", TraverseTests[Stream].traverse[Int, Int, Int, List[Int], Option, Option])
checkAll("Traverse[Stream]", SerializableTests.serializable(Traverse[Stream]))

test("show") {
Stream(1, 2, 3).show should === ("Stream(1, ?)")
Stream.empty[Int].show should === ("Stream()")
}

test("Show[Stream] is referentially transparent, unlike Stream.toString") {
forAll { stream: Stream[Int] =>
if (!stream.isEmpty) {
val unevaluatedStream = stream map identity
val initialShow = unevaluatedStream.show

// Evaluating the tail can cause Stream.toString to return different values,
// depending on the internal state of the Stream. Show[Stream] should return
// consistent values independent of internal state.
unevaluatedStream.tail
initialShow should === (unevaluatedStream.show)
} else {
stream.show should === (stream.toString)
}
}
}
}