/*
* Copyright (c) 2018. Phasmid Software
*/
package edu.neu.coe.csye7200.asstll
/**
* Trait to define the behavior of something that behaves like a list.
*
* This trait is extended by the LazyList classes.
*
* @tparam X the underlying type of this Monad
*/
trait ListLike[+X] extends Monadic[X] with IterableOnce[X] {
self =>
/**
* Method to yield the size of this list-like object.
*
* @return Some(n) where n is size if its definite; if size is not known (lazy) then return None
*/
def size(): Option[Int]
/**
* Construct a (finite) ListLike[X]
with exactly one element.
* Overrides the definition from Monadic by making the result type more specific.
*
* Note that this is an instance method.
*
* @param y the value of the element.
* @tparam Y the type of y
and the underlying type of the resulting ListLike object
* @return a ListLike[Y]
with exactly one element (whose value is y
).
*/
def unit[Y](y: Y): ListLike[Y]
/**
* Construct a ListLike[X]
with the elements of ys
.
*
* Note that this is an instance method.
*
* @param ys the sequence of elements with which to construct the list-like object.
* @tparam Y the underlying type of ys
and the underlying type of the resulting ListLike object
* @return a ListLike[Y]
with exactly one element (whose value is y
).
*/
def build[Y](ys: Seq[Y]): ListLike[Y]
/**
* The map function.
* Overrides the definition from Monadic by making the result type more specific.
*
* @param f a function which converts an X
into a Y
.
* @tparam Y the underlying type of the result.
* @return a ListLike[Y]
where each element is the result of applying f
to the corresponding
* element of this
.
*/
def map[Y](f: X => Y): ListLike[Y]
/**
* The flatMap function.
* Overrides the definition from Monadic by making the result type more specific.
*
* @param f a function which converts an X
into a LazyList[Y]
.
* @tparam Y the underlying type of the result.
* @return a ListLike[Y]
where each element is the result of applying f
to the corresponding
* element of this
and then flattening the result
* by concatenating all streams together.
*/
def flatMap[Y](f: X => Monadic[Y]): ListLike[Y]
/**
* The filter function.
* Overrides the definition from Monadic by making the result type more specific.
*
* @param p a predicate which takes an X
and yields a Boolean
.
* @return a ListLike[X]
where every element satisfies the predicate p
.
*/
def filter(p: X => Boolean): ListLike[X]
/**
* The filterNot function.
* Overrides the definition from Monadic by making the result type more specific.
*
* @param p a predicate which takes an X
and yields a Boolean
.
* @return a ListLike[X]
where every element satisfies the predicate p
.
*/
def filterNot(p: X => Boolean): ListLike[X]
/**
* Method to determine if this ListLike object is empty.
*
* @return true if the list is empty.
*/
def isEmpty: Boolean
/**
* @return the head of this list
*/
def head: X
/**
* @return the tail of this list
*/
def tail: ListLike[X]
/**
* Method to form a new list-like object by pre-pending y
*
* @param y the value to serve as the new head
* @tparam Y the type of y
* @return a new ListLike[Y]
object with y as its head and this as its tail
*/
def +:[Y >: X](y: Y): ListLike[Y]
/**
* Concatenate this LazyList with ys.
*
* CONSIDER moving to LazyListLike
*
* @param ys the stream to be used if/when this stream is exhausted.
* @tparam Y the underlying type of ys and the result.
* @return a ListLike[Y]
which contains all the elements of this followed by all the elements of ys.
*/
def ++[Y >: X](ys: ListLike[Y]): ListLike[Y]
/**
* Method to zip to ListLike objects together
*
* @param ys the stream of Ys
* @tparam Y the underlying type of ys
* @return a ListLike[(X,Y)]
where each element is a tuple of the corresponding elements from this
* and ys respectively.
*/
def zip[Y](ys: ListLike[Y]): ListLike[(X, Y)]
/**
* Take the first n elements of this ListLike object as a ListLike object.
*
* @param n the number of elements to take (must not be negative).
* @return a ListLike[(X,Y)]
of length n.
*/
def take(n: Int): ListLike[X]
/**
* Drop the first n elements of this ListLike object and return the remainder as a ListLike object.
*
* @param n the number of elements to drop (must not be negative).
* @return a ListLike[(X,Y)]
which is shorter than this by n.
*/
def drop(n: Int): ListLike[X]
/** Necessary to keep this from being implicitly converted to
* [[scala.collection.Iterable]]
in `for` comprehensions.
*/
@inline final def withFilter(p: X => Boolean): WithFilter = new WithFilter(p)
/** We need a whole WithFilter class to honor the doesnt create a new
* collection contract.
*/
class WithFilter(p: X => Boolean) {
def map[B](f: X => B): ListLike[B] = self filter p map f
def flatMap[B](f: X => ListLike[B]): ListLike[B] = self filter p flatMap f
//def foreach[U](f: X => U): Unit = self filter p foreach f
def withFilter(q: X => Boolean): WithFilter = new WithFilter(x => p(x) && q(x))
}
/**
* Method to flatten a ListLike[Monadic[Y]
* This is an instance method because it used the build method.
* It does NOT refer to any other information about this ListLike object.
*
* @param ms a ListLike[Seq[Y]
to be flattened
* @tparam Y the underlying type of ms and the result
* @return a ListLike[(X,Y)]
*/
def flatten[Y](ms: ListLike[Seq[Y]]): ListLike[Y] = flatten(ms.toSeq)
/**
* Method to flatten a ListLike[Monadic[Y]
* This is an instance method because it used the build method.
* It does NOT refer to any other information about this ListLike object.
*
* CONSIDER simplifying
*
* @param yss Seq[Seq[Y]
to be flattened
* @tparam Y the underlying type of ms and the result
* @return a ListLike[(X,Y)]
*/
def flatten[Y](yss: Seq[Seq[Y]]): ListLike[Y] = build(yss.foldLeft[Seq[Y]](Seq())((_: Seq[Y]) ++ (_: Seq[Y])))
}
/**
* Trait to define functor behavior
*
* @tparam X the underlying type of this Functor
*/
trait Functor[+X] {
/**
* The map function.
*
* @param f a function which converts an X
into a Y
.
* @tparam Y the underlying type of the result.
* @return a Functor[Y]
where each element is the result of applying f
to the corresponding
* element of this
.
*/
def map[Y](f: X => Y): Functor[Y]
}
/**
* Trait to define monadic behavior.
*
* @tparam X the underlying type of this Monad
*/
trait Monadic[+X] extends Functor[X] {
/**
* Construct a (finite) LazyList[X]
with exactly one element.
*
* @param y the value of the element.
* @tparam Y the underlying type of the resulting monad
* @return a Monadic[Y]
with exactly one element (whose value is x
).
*/
def unit[Y >: X](y: Y): Monadic[Y]
/**
* The map function.
* Overrides the definition form Functor by making the result type more specific.
*
* @param f a function which converts an X
into a Y
.
* @tparam Y the underlying type of the result.
* @return a Monadic[Y]
where each element is the result of applying f
to the corresponding
* element of this
.
*/
def map[Y](f: X => Y): Monadic[Y]
/**
* The flatMap function.
*
* @param f a function which converts an X
LazyList[Y].
* @tparam Y the underlying type of the result.
* @return a LazyList[Y]
where each element is the result of applying f
to the corresponding
* element of this
and then flattening the result
* by concatenating all streams together.
*/
def flatMap[Y](f: X => Monadic[Y]): Monadic[Y]
/**
* The filter function.
*
* @param p a predicate which takes an X
and yields a Boolean
.
* @return a Monadic[X]
where every element satisfies the predicate p
.
*/
def filter(p: X => Boolean): Monadic[X]
/**
* The filterNot function.
*
* @param p a predicate which takes an X
and yields a Boolean
.
* @return a ListLike[X]
where every element satisfies the predicate p
.
*/
def filterNot(p: X => Boolean): Monadic[X]
/**
* Convert this Monadic[X]
into a Seq[X]
, element for element.
*
* @return a Seq[X]
*/
def toSeq: Seq[X]
}
Reviews
There are no reviews yet.