PageRenderTime 24ms CodeModel.GetById 1ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/main/scala/scalaz/NonEmptyList.scala

http://github.com/scalaz/scalaz
Scala | 265 lines | 188 code | 67 blank | 10 comment | 5 complexity | 3239fa4c24700d1fe560fb9938feb36d MD5 | raw file
  1package scalaz
  2
  3/** A singly-linked list that is guaranteed to be non-empty. */
  4final class NonEmptyList[A] private[scalaz](val head: A, val tail: IList[A]) {
  5  import NonEmptyList._
  6  import Zipper._
  7  import scalaz.Liskov._
  8
  9
 10  def <::(b: A): NonEmptyList[A] = nel(b, head :: tail)
 11
 12  def <:::(bs: IList[A]): NonEmptyList[A] = bs match {
 13    case INil() => this
 14    case ICons(b, bs) => nel(b, bs ::: list)
 15  }
 16
 17  def :::>(bs: IList[A]): NonEmptyList[A] = nel(head, tail ::: bs)
 18
 19  /** Append one nonempty list to another. */
 20  def append(f2: NonEmptyList[A]): NonEmptyList[A] = list <::: f2
 21
 22  def map[B](f: A => B): NonEmptyList[B] = nel(f(head), tail.map(f))
 23
 24  /** @since 7.0.3 */
 25  def foreach(f: A => Unit): Unit = {
 26    f(head)
 27    tail.foldLeft(()){(_, a) =>
 28      f(a)
 29      ()
 30    }
 31  }
 32
 33  def flatMap[B](f: A => NonEmptyList[B]): NonEmptyList[B] = {
 34    val rev = reverse
 35    rev.tail.foldLeft(f(rev.head))((nel, b) => f(b) append nel)
 36  }
 37
 38  def distinct(implicit A: Order[A]): NonEmptyList[A] =
 39    (list.distinct: @unchecked) match {
 40      case ICons(x, xs) => nel(x, xs)
 41    }
 42
 43  def traverse1[F[_], B](f: A => F[B])(implicit F: Apply[F]): F[NonEmptyList[B]] = {
 44    tail match {
 45      case INil() => F.map(f(head))(nel(_, IList.empty))
 46      case ICons(b, bs) => F.apply2(f(head), OneAnd.oneAndTraverse[IList].traverse1(OneAnd(b, bs))(f)) {
 47        case (h, t) => nel(h, t.head :: t.tail)
 48      }
 49    }
 50  }
 51
 52  def list: IList[A] = head :: tail
 53
 54  def stream: Stream[A] = head #:: tail.toStream
 55
 56  def toZipper: Zipper[A] = zipper(Stream.Empty, head, tail.toStream)
 57
 58  def zipperEnd: Zipper[A] = {
 59    import Stream._
 60    tail.reverse match {
 61      case INil()     => zipper(empty, head, empty)
 62      case ICons(t, ts) => zipper(ts.toStream :+ head, t, empty)
 63    }
 64  }
 65
 66  /** @since 7.0.2 */
 67  def init: IList[A] = tail.initMaybe.cata(il => head :: il, IList.empty[A])
 68
 69  def inits: NonEmptyList[NonEmptyList[A]] =
 70    reverse.tails.map(_.reverse)
 71
 72  /** @since 7.0.2 */
 73  def last: A = tail.lastOption.getOrElse(head)
 74
 75  def tails: NonEmptyList[NonEmptyList[A]] = {
 76    @annotation.tailrec
 77    def tails0(as: NonEmptyList[A], accum: IList[NonEmptyList[A]]): NonEmptyList[NonEmptyList[A]] =
 78      as.tail match {
 79        case INil() => nel(as, accum).reverse
 80        case ICons(h, t) => tails0(nel(h, t), as :: accum)
 81      }
 82    tails0(this, IList.empty)
 83  }
 84
 85  def reverse: NonEmptyList[A] = (list.reverse: @unchecked) match {
 86    case ICons(x, xs) => nel(x, xs)
 87  }
 88
 89  /** @since 7.0.2 */
 90
 91  def sortBy[B](f: A => B)(implicit o: Order[B]): NonEmptyList[A] = (list.sortBy(f): @unchecked) match {
 92    case ICons(x, xs) => nel(x, xs)
 93  }
 94
 95  /** @since 7.0.2 */
 96  def sortWith(lt: (A, A) => Boolean): NonEmptyList[A] =
 97    (list.toList.sortWith(lt): @unchecked) match {
 98      case x :: xs => nel(x, IList.fromList(xs))
 99    }
100
101  /** @since 7.0.2 */
102  def sorted(implicit o: Order[A]): NonEmptyList[A] = (list.sorted(o): @unchecked) match {
103    case ICons(x, xs) => nel(x, xs)
104  }
105
106  def size: Int = 1 + tail.length
107
108  def zip[B](b: => NonEmptyList[B]): NonEmptyList[(A, B)] = {
109    val _b = b
110    nel((head, _b.head), tail zip _b.tail)
111  }
112
113  def unzip[X, Y](implicit ev: A <~< (X, Y)): (NonEmptyList[X], NonEmptyList[Y]) = {
114    val (a, b) = ev(head)
115    val (aa, bb) = tail.unzip: (IList[X], IList[Y])
116    (nel(a, aa), nel(b, bb))
117 }
118
119  def zipWithIndex: NonEmptyList[(A, Int)] = {
120    @annotation.tailrec
121    def loop(as: IList[A], i: Int, acc: IList[(A, Int)]): IList[(A, Int)] =
122      as match {
123        case ICons(x, y) => loop(y, i + 1, (x, i) :: acc)
124        case _ => acc.reverse
125      }
126    new NonEmptyList((head, 0), loop(tail, 1, IList.empty))
127  }
128
129  override def toString: String = "NonEmpty" + (head :: tail)
130
131  override def equals(any: Any): Boolean =
132    any match {
133      case that: NonEmptyList[_] => this.list == that.list
134      case _                     => false
135    }
136
137  override def hashCode: Int =
138    list.hashCode
139}
140
141object NonEmptyList extends NonEmptyListInstances {
142  // optimised versions of apply(A*)
143  @inline final def apply[A](a: A): NonEmptyList[A] = nel(a, IList.empty)
144  @inline final def apply[A](a: A, b: A): NonEmptyList[A] = nel(a, IList(b))
145  @inline final def apply[A](a: A, b: A, c: A): NonEmptyList[A] = nel(a, IList(b, c))
146  @inline final def apply[A](a: A, b: A, c: A, d: A): NonEmptyList[A] = nel(a, IList(b, c, d))
147  @inline final def apply[A](a: A, b: A, c: A, d: A, e: A): NonEmptyList[A] = nel(a, IList(b, c, d, e))
148  @inline final def apply[A](a: A, b: A, c: A, d: A, e: A, f: A): NonEmptyList[A] = nel(a, IList(b, c, d, e, f))
149
150  @inline final def apply[A](a: A, b: A, c: A, d: A, e: A, f: A, as: A*): NonEmptyList[A] = a <:: b <:: c <:: d <:: e <:: fromSeq(f, as)
151
152  def fromSeq[A](h: A, t: Seq[A]): NonEmptyList[A] =
153    nel(h, IList.fromSeq(t))
154
155  def unapply[A](v: NonEmptyList[A]): Option[(A, IList[A])] =
156    Some((v.head, v.tail))
157
158  def nel[A](h: A, t: IList[A]): NonEmptyList[A] =
159    new NonEmptyList(h, t)
160
161  def lift[A, B](f: NonEmptyList[A] => B): IList[A] => Option[B] = {
162    case INil() => None
163    case ICons(h, t) => Some(f(NonEmptyList.nel(h, t)))
164  }
165}
166
167sealed abstract class NonEmptyListInstances0 {
168  implicit def nonEmptyListEqual[A: Equal]: Equal[NonEmptyList[A]] = Equal.equalBy[NonEmptyList[A], IList[A]](_.list)(IList.equal[A])
169}
170
171sealed abstract class NonEmptyListInstances extends NonEmptyListInstances0 {
172  implicit val nonEmptyList: Traverse1[NonEmptyList] with Monad[NonEmptyList] with Alt[NonEmptyList] with BindRec[NonEmptyList] with Plus[NonEmptyList] with Comonad[NonEmptyList] with Zip[NonEmptyList] with Unzip[NonEmptyList] with Align[NonEmptyList] =
173    new Traverse1[NonEmptyList] with Monad[NonEmptyList] with Alt[NonEmptyList] with BindRec[NonEmptyList] with Plus[NonEmptyList] with Comonad[NonEmptyList] with Zip[NonEmptyList] with Unzip[NonEmptyList] with Align[NonEmptyList] {
174      override def findLeft[A](fa: NonEmptyList[A])(f: A => Boolean) =
175        if(f(fa.head)) Some(fa.head) else fa.tail.find(f).toOption
176
177      override def foldMap[A, B](fa: NonEmptyList[A])(f: A => B)(implicit M: Monoid[B]) =
178        Foldable[IList].foldMap(fa.list)(f)(M)
179
180      override def traverse1[F[_], A, B](fa: NonEmptyList[A])(f: A => F[B])(implicit F: Apply[F]) = {
181        val revOpt: Maybe[F[NonEmptyList[B]]] =
182          F.unfoldrOpt[IList[A], B, NonEmptyList[B]](fa.list)(_ match {
183            case ICons(a, as) => Maybe.just((f(a), as))
184            case INil() => Maybe.empty
185          })(Reducer.ReverseNonEmptyListReducer[B])
186
187        val rev: F[NonEmptyList[B]] = revOpt getOrElse sys.error("Head cannot be empty")
188        F.map(rev)(_.reverse)
189      }
190
191      def traverse1Impl[G[_] : Apply, A, B](fa: NonEmptyList[A])(f: A => G[B]): G[NonEmptyList[B]] =
192        fa traverse1 f
193
194      override def foldMapRight1[A, B](fa: NonEmptyList[A])(z: A => B)(f: (A, => B) => B): B = {
195        val reversed = fa.reverse
196        reversed.tail.foldLeft(z(reversed.head))((x, y) => f(y, x))
197      }
198
199      override def foldMapLeft1[A, B](fa: NonEmptyList[A])(z: A => B)(f: (B, A) => B): B =
200        fa.tail.foldLeft(z(fa.head))(f)
201
202      override def foldMap1[A, B](fa: NonEmptyList[A])(f: A => B)(implicit F: Semigroup[B]): B = {
203        fa.tail.foldLeft(f(fa.head))((x, y) => F.append(x, f(y)))
204      }
205
206      override def psumMap1[A, B, G[_]](fa: NonEmptyList[A])(f: A => G[B])(implicit G: Plus[G]): G[B] =
207        fa.tail match {
208          case INil() => f(fa.head)
209          case ICons(snd, rest) => G.plus(f(fa.head), psumMap1(NonEmptyList.nel(snd, rest))(f)(G))
210        }
211
212      // would otherwise use traverse1Impl
213      override def foldLeft[A, B](fa: NonEmptyList[A], z: B)(f: (B, A) => B): B =
214        fa.tail.foldLeft(f(z, fa.head))(f)
215
216      def bind[A, B](fa: NonEmptyList[A])(f: A => NonEmptyList[B]): NonEmptyList[B] = fa flatMap f
217
218      def point[A](a: => A): NonEmptyList[A] = NonEmptyList(a)
219
220      def plus[A](a: NonEmptyList[A], b: => NonEmptyList[A]): NonEmptyList[A] = a.list <::: b
221
222      def alt[A](a: => NonEmptyList[A], b: => NonEmptyList[A]): NonEmptyList[A] = plus(a, b)
223
224      def copoint[A](p: NonEmptyList[A]): A = p.head
225
226      def cobind[A, B](fa: NonEmptyList[A])(f: NonEmptyList[A] => B): NonEmptyList[B] = map(cojoin(fa))(f)
227
228      override def cojoin[A](a: NonEmptyList[A]): NonEmptyList[NonEmptyList[A]] = a.tails
229
230      def zip[A, B](a: => NonEmptyList[A], b: => NonEmptyList[B]) = a zip b
231
232      def unzip[A, B](a: NonEmptyList[(A, B)]) = a.unzip
233
234      def alignWith[A, B, C](f: A \&/ B => C) = (a, b) => {
235        NonEmptyList.nel(f(\&/.Both(a.head, b.head)), Align[IList].alignWith(f)(a.tail, b.tail))
236      }
237
238      override def length[A](a: NonEmptyList[A]): Int = a.size
239
240      override def toNel[A](fa: NonEmptyList[A]) = fa
241
242      override def toIList[A](fa: NonEmptyList[A]) = fa.list
243
244      override def all[A](fa: NonEmptyList[A])(f: A => Boolean) =
245        f(fa.head) && Foldable[IList].all(fa.tail)(f)
246
247      override def any[A](fa: NonEmptyList[A])(f: A => Boolean) =
248        f(fa.head) || Foldable[IList].any(fa.tail)(f)
249
250      def tailrecM[A, B](a: A)(f: A => NonEmptyList[A \/ B]): NonEmptyList[B] =
251        (BindRec[IList].tailrecM[A, B](a)(a => f(a).list): @unchecked) match {
252          case ICons(h, t) => NonEmptyList.nel(h, t)
253        }
254    }
255
256  implicit def nonEmptyListSemigroup[A]: Semigroup[NonEmptyList[A]] = new Semigroup[NonEmptyList[A]] {
257    def append(f1: NonEmptyList[A], f2: => NonEmptyList[A]) = f1 append f2
258  }
259
260  implicit def nonEmptyListShow[A: Show]: Show[NonEmptyList[A]] =
261    Contravariant[Show].contramap(IList.show[A])(_.list)
262
263  implicit def nonEmptyListOrder[A: Order]: Order[NonEmptyList[A]] =
264    Order.orderBy[NonEmptyList[A], IList[A]](_.list)(IList.order[A])
265}