Skip to content

Commit

Permalink
Add cobind to Ephemeral stream & check laws.
Browse files Browse the repository at this point in the history
  • Loading branch information
Declan Conlon authored and possiblywrong committed Sep 10, 2013
1 parent 7b7f9e0 commit d28b5db
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
33 changes: 32 additions & 1 deletion core/src/main/scala/scalaz/EphemeralStream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ sealed abstract class EphemeralStream[A] {
foldLeft(0)(addOne _)
}

def tails: EphemeralStream[EphemeralStream[A]] =
if (isEmpty) emptyEphemeralStream
else cons(this, tail().tails)

def inits: EphemeralStream[EphemeralStream[A]] =
if (isEmpty) emptyEphemeralStream
else EphemeralStream[A]() ##:: tail().inits.map(head() ##:: _)

def findM[M[_]: Monad](p: A => M[Boolean]): M[Option[A]] =
if(isEmpty)
Monad[M].point(None)
Expand Down Expand Up @@ -122,11 +130,30 @@ object EphemeralStream extends EphemeralStreamInstances with EphemeralStreamFunc
if (b < size) Some((as0(b), b + 1))
else None)
}

class ConsWrap[A](e: => EphemeralStream[A]) {
def ##::(h: A): EphemeralStream[A] = cons(h, e)
}

implicit def consWrapper[A](e: => EphemeralStream[A]): ConsWrap[A] =
new ConsWrap[A](e)

object ##:: {
def unapply[A](xs: EphemeralStream[A]): Option[(A, EphemeralStream[A])] =
if (xs.isEmpty) None
else Some((xs.head(), xs.tail()))
}
}

sealed abstract class EphemeralStreamInstances {
// TODO more instances
implicit val ephemeralStreamInstance = new MonadPlus[EphemeralStream] with Zip[EphemeralStream] with Unzip[EphemeralStream] with Traverse[EphemeralStream] {
implicit val ephemeralStreamInstance: MonadPlus[EphemeralStream] with Zip[EphemeralStream] with Unzip[EphemeralStream] with Traverse[EphemeralStream] with Cobind[EphemeralStream] = new MonadPlus[EphemeralStream] with Zip[EphemeralStream] with Unzip[EphemeralStream] with Traverse[EphemeralStream] with Cobind[EphemeralStream] {
import EphemeralStream._
override def cojoin[A](a: EphemeralStream[A]): EphemeralStream[EphemeralStream[A]] = a match {
case _ ##:: tl => if (tl.isEmpty) EphemeralStream(a)
else a ##:: cojoin(tl)
}
def cobind[A, B](fa: EphemeralStream[A])(f: EphemeralStream[A] => B): EphemeralStream[B] = map(cojoin(fa))(f)
def plus[A](a: EphemeralStream[A], b: => EphemeralStream[A]) = a ++ b
def bind[A, B](fa: EphemeralStream[A])(f: A => EphemeralStream[B]) = fa flatMap f
def point[A](a: => A) = EphemeralStream(a)
Expand Down Expand Up @@ -188,6 +215,10 @@ trait EphemeralStreamFunctions {
case h #:: t => cons(h, fromStream(t))
}

def fromIterable[A](i: Iterable[A]): EphemeralStream[A] =
if (i.isEmpty) emptyEphemeralStream
else i.head ##:: fromIterable(i.tail)

implicit def toIterable[A](e: EphemeralStream[A]): Iterable[A] = new Iterable[A] {
def iterator = new Iterator[A] {
var cur = e
Expand Down
1 change: 1 addition & 0 deletions tests/src/test/scala/scalaz/EphemeralStreamTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class EphemeralStreamTest extends Spec {
checkAll(monadPlus.laws[EphemeralStream])
checkAll(traverse.laws[EphemeralStream])
checkAll(zip.laws[EphemeralStream])
checkAll(cobind.laws[EphemeralStream])

implicit def ephemeralStreamShow[A: Show]: Show[EphemeralStream[A]] =
Show[List[A]].contramap(_.toList)
Expand Down

0 comments on commit d28b5db

Please sign in to comment.