Skip to content

Commit 31ecdac

Browse files
author
Luka Jacobowitz
committed
Add more docs
1 parent bab788b commit 31ecdac

File tree

3 files changed

+134
-16
lines changed

3 files changed

+134
-16
lines changed

core/src/main/scala/cats/data/NonEmptyMap.scala

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,32 +28,128 @@ final class NonEmptyMap[K, A] private(val value: SortedMap[K, A]) extends AnyVal
2828
private implicit def ordering: Ordering[K] = value.ordering
2929
private implicit def order: Order[K] = Order.fromOrdering
3030

31+
/**
32+
* Alias for [[concat]]
33+
*/
3134
def ++(as: NonEmptyMap[K, A]): NonEmptyMap[K, A] = concat(as)
35+
/**
36+
* Appends this NEM to another NEM, producing a new `NonEmptyMap`.
37+
*/
3238
def concat(as: NonEmptyMap[K, A]): NonEmptyMap[K, A] = new NonEmptyMap(value ++ as.value)
39+
40+
/**
41+
* Removes a key from this map, returning a new SortedMap.
42+
*/
3343
def -(key: K): SortedMap[K, A] = value - key
44+
45+
/**
46+
* Adds a key-value pair to this map, returning a new `NonEmptyMap`.
47+
* */
3448
def +(ka: (K, A)): NonEmptyMap[K, A] = new NonEmptyMap(value + ka)
3549

50+
/**
51+
* Applies f to all the elements
52+
*/
3653
def map[B](f: A B): NonEmptyMap[K, B] =
3754
new NonEmptyMap(Functor[SortedMap[K, ?]].map(value)(f))
3855

56+
/**
57+
* Optionally returns the value associated with the given key.
58+
* {{{
59+
* scala> import cats.data.NonEmptyMap
60+
* scala> import cats.implicits._
61+
* scala> val nem = NonEmptyMap.of("A" -> 1, "B" -> 2)
62+
* scala> nem.get("B")
63+
* res0: Option[Int] = Some(2)
64+
* }}}
65+
*/
3966
def get(k: K): Option[A] = value.get(k)
4067

68+
/**
69+
* Returns a `SortedSet` containing all the keys of this map.
70+
* {{{
71+
* scala> import cats.data.NonEmptyMap
72+
* scala> import cats.implicits._
73+
* scala> val nem = NonEmptyMap.of(1 -> "A", 2 -> "B")
74+
* scala> nem.keys
75+
* res0: scala.collection.immutable.SortedSet[Int] = Set(1, 2)
76+
* }}}
77+
*/
4178
def keys: SortedSet[K] = value.keySet
4279

80+
/**
81+
* Converts this map to a `NonEmptyList` of key-value pairs.
82+
*
83+
* {{{
84+
* scala> import cats.data.NonEmptyMap
85+
* scala> import cats.implicits._
86+
* scala> val nem = NonEmptyMap.of(1 -> "A", 2 -> "B")
87+
* scala> nem.toNonEmptyList
88+
* res0: cats.data.NonEmptyList[(Int, String)] = NonEmptyList((1,A), (2,B))
89+
* }}}
90+
*/
4391
def toNonEmptyList: NonEmptyList[(K, A)] = NonEmptyList.fromListUnsafe(value.toList)
4492

93+
/**
94+
* Returns the first key-value pair of this map.
95+
*/
4596
def head: (K, A) = value.head
97+
/**
98+
* Returns the first key-value pair of this map.
99+
*/
46100
def last: (K, A) = value.last
101+
102+
/**
103+
* Returns all the key-value pairs, except for the first.
104+
*/
47105
def tail: SortedMap[K, A] = value.tail
48106

107+
/**
108+
* Alias for [[get]]
109+
*
110+
* {{{
111+
* scala> import cats.data.NonEmptyMap
112+
* scala> import cats.implicits._
113+
* scala> val nem = NonEmptyMap.of("A" -> 1, "B" -> 2)
114+
* scala> nem("A")
115+
* res0: Option[Int] = Some(1)
116+
* }}}
117+
*/
49118
def apply(key: K): Option[A] = get(key)
119+
120+
/**
121+
* Checks whether this map contains a binding for the given key.
122+
*/
50123
def contains(key: K): Boolean = value.contains(key)
51124

125+
/**
126+
* Returns the amount of key-value pars in this map.
127+
*/
52128
def size: Int = value.size
129+
130+
/**
131+
* Tests whether a predicate holds for all elements of this map.
132+
*/
53133
def forall(p: A Boolean): Boolean = value.forall { case (_, a) => p(a) }
134+
135+
/**
136+
* Tests whether a predicate holds for at least one element of this map.
137+
*/
54138
def exists(f: A Boolean): Boolean = value.exists { case (_, a) => f(a) }
139+
140+
/**
141+
* Returns the first value along with its key, that matches the given predicate.
142+
*/
55143
def find(f: A Boolean): Option[(K, A)] = value.find { case (_, a) => f(a) }
144+
145+
/**
146+
* Filters all elements of this map that do not satisfy the given predicate.
147+
*/
56148
def filter(p: A Boolean): SortedMap[K, A] = value.filter { case (_, a) => p(a) }
149+
150+
/**
151+
* Filters all elements of this map that satisfy the given predicate.
152+
*/
57153
def filterNot(p: A Boolean): SortedMap[K, A] = filter(t => !p(t))
58154

59155

@@ -75,6 +171,11 @@ final class NonEmptyMap[K, A] private(val value: SortedMap[K, A]) extends AnyVal
75171
def reduceLeft(f: (A, A) => A): A =
76172
reduceLeftTo(identity)(f)
77173

174+
175+
/**
176+
* Apply `f` to the "initial element" of this map and lazily combine it
177+
* with every other value using the given function `g`.
178+
*/
78179
def reduceLeftTo[B](f: A => B)(g: (B, A) => B): B =
79180
tail.foldLeft(f(head._2))((b, a) => g(b, a._2))
80181

@@ -84,6 +185,10 @@ final class NonEmptyMap[K, A] private(val value: SortedMap[K, A]) extends AnyVal
84185
def reduceRight(f: (A, Eval[A]) => Eval[A]): Eval[A] =
85186
reduceRightTo(identity)(f)
86187

188+
/**
189+
* Apply `f` to the "initial element" of this map and lazily combine it
190+
* with every other value using the given function `g`.
191+
*/
87192
def reduceRightTo[B](f: A => B)(g: (A, Eval[B]) => Eval[B]): Eval[B] =
88193
Always((head, tail)).flatMap { case ((_, a), ga) =>
89194
Foldable[SortedMap[K, ?]].reduceRightToOption(ga)(f)(g).flatMap {
@@ -107,6 +212,11 @@ final class NonEmptyMap[K, A] private(val value: SortedMap[K, A]) extends AnyVal
107212
}
108213
}
109214

215+
/**
216+
* Given a function which returns a G effect, thread this effect
217+
* through the running of this function on all the values in this map,
218+
* returning an NonEmptyMap[K, B] in a G context.
219+
*/
110220
def nonEmptyTraverse[G[_], B](f: A => G[B])(implicit G: Apply[G]): G[NonEmptyMap[K, B]] =
111221
reduceRightToOptionWithKey[A, G[SortedMap[K, B]]](tail)({ case (k, a) =>
112222
G.map(f(a))(b => SortedMap.empty[K, B] + ((k, b)))
@@ -117,7 +227,10 @@ final class NonEmptyMap[K, A] private(val value: SortedMap[K, A]) extends AnyVal
117227
case Some(gtail) => G.map2(f(head._2), gtail)((a, bs) => NonEmptyMap((head._1, a), bs))
118228
}.value
119229

120-
def toMap: SortedMap[K, A] = value
230+
/**
231+
* Converts this map to a `SortedMap`.
232+
*/
233+
def toSortedMap: SortedMap[K, A] = value
121234

122235
/**
123236
* Typesafe stringification method.
@@ -129,6 +242,8 @@ final class NonEmptyMap[K, A] private(val value: SortedMap[K, A]) extends AnyVal
129242
def show(implicit A: Show[A], K: Show[K]): String =
130243
s"NonEmpty${Show[SortedMap[K, A]].show(value)}"
131244

245+
override def toString: String = s"NonEmpty${toSortedMap.toString}"
246+
132247
/**
133248
* Typesafe equality operator.
134249
*
@@ -138,8 +253,11 @@ final class NonEmptyMap[K, A] private(val value: SortedMap[K, A]) extends AnyVal
138253
* universal equality provided by .equals.
139254
*/
140255
def ===(that: NonEmptyMap[K, A])(implicit A: Eq[A]): Boolean =
141-
Eq[SortedMap[K, A]].eqv(value, that.toMap)
256+
Eq[SortedMap[K, A]].eqv(value, that.toSortedMap)
142257

258+
/**
259+
* Alias for [[size]]
260+
*/
143261
def length: Int = size
144262

145263
}

laws/src/main/scala/cats/laws/discipline/Arbitrary.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ object arbitrary extends ArbitraryInstances0 {
8181
} yield NonEmptyMap((k, a), fa))
8282

8383
implicit def cogenNonEmptyMap[K: Order : Cogen, A: Order : Cogen]: Cogen[NonEmptyMap[K, A]] =
84-
Cogen[SortedMap[K, A]].contramap(_.toMap)
84+
Cogen[SortedMap[K, A]].contramap(_.toSortedMap)
8585

8686
implicit def catsLawsArbitraryForEitherT[F[_], A, B](implicit F: Arbitrary[F[Either[A, B]]]): Arbitrary[EitherT[F, A, B]] =
8787
Arbitrary(F.arbitrary.map(EitherT(_)))

tests/src/test/scala/cats/tests/NonEmptyMapSuite.scala

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,43 +48,43 @@ class NonEmptyMapSuite extends CatsSuite {
4848

4949
test("NonEmptyMap#filter is consistent with Map#filter") {
5050
forAll { (nem: NonEmptyMap[String, Int], p: Int => Boolean) =>
51-
val map = nem.toMap
51+
val map = nem.toSortedMap
5252
nem.filter(p) should ===(map.filter(t => p(t._2)))
5353
}
5454
}
5555

5656
test("NonEmptyMap#filterNot is consistent with Map#filterNot") {
5757
forAll { (nem: NonEmptyMap[String, Int], p: Int => Boolean) =>
58-
val map = nem.toMap
58+
val map = nem.toSortedMap
5959
nem.filterNot(p) should ===(map.filterNot(t => p(t._2)))
6060
}
6161
}
6262

6363
test("NonEmptyMap#find is consistent with Map#find") {
6464
forAll { (nem: NonEmptyMap[String, Int], p: Int => Boolean) =>
65-
val map = nem.toMap
65+
val map = nem.toSortedMap
6666
nem.find(p).map(_._2) should ===(map.find(p))
6767
}
6868
}
6969

7070
test("NonEmptyMap#exists is consistent with Map#exists") {
7171
forAll { (nem: NonEmptyMap[String, Int], p: Int => Boolean) =>
72-
val map = nem.toMap
72+
val map = nem.toSortedMap
7373
nem.exists(p) should ===(map.exists(p))
7474
}
7575
}
7676

7777
test("NonEmptyMap#forall is consistent with Map#forall") {
7878
forAll { (nem: NonEmptyMap[String, Int], p: Int => Boolean) =>
79-
val map = nem.toMap
79+
val map = nem.toSortedMap
8080
nem.forall(p) should ===(map.forall(p))
8181
}
8282
}
8383

8484
test("NonEmptyMap#map is consistent with Map#map") {
8585
forAll { (nem: NonEmptyMap[String, Int], p: Int => String) =>
86-
val map = nem.toMap
87-
nem.map(p).toMap should ===(map.fmap(p))
86+
val map = nem.toSortedMap
87+
nem.map(p).toSortedMap should ===(map.fmap(p))
8888
}
8989
}
9090

@@ -157,17 +157,17 @@ class NonEmptyMapSuite extends CatsSuite {
157157

158158
test("fromMap round trip") {
159159
forAll { l: SortedMap[String, Int] =>
160-
NonEmptyMap.fromMap(l).map(_.toMap).getOrElse(SortedMap.empty[String, Int]) should ===(l)
160+
NonEmptyMap.fromMap(l).map(_.toSortedMap).getOrElse(SortedMap.empty[String, Int]) should ===(l)
161161
}
162162

163163
forAll { nem: NonEmptyMap[String, Int] =>
164-
NonEmptyMap.fromMap(nem.toMap) should ===(Some(nem))
164+
NonEmptyMap.fromMap(nem.toSortedMap) should ===(Some(nem))
165165
}
166166
}
167167

168168
test("fromMapUnsafe/fromMap consistency") {
169169
forAll { nem: NonEmptyMap[String, Int] =>
170-
NonEmptyMap.fromMap(nem.toMap) should ===(Some(NonEmptyMap.fromMapUnsafe(nem.toMap)))
170+
NonEmptyMap.fromMap(nem.toSortedMap) should ===(Some(NonEmptyMap.fromMapUnsafe(nem.toSortedMap)))
171171
}
172172
}
173173

@@ -179,14 +179,14 @@ class NonEmptyMapSuite extends CatsSuite {
179179

180180
test("+ consistent with Map") {
181181
forAll { (nem: NonEmptyMap[String, Int], i: (String, Int)) =>
182-
(nem + i).toMap should ===(nem.toMap + i)
182+
(nem + i).toSortedMap should ===(nem.toSortedMap + i)
183183
}
184184
}
185185

186186
test("NonEmptyMap#size and length is consistent with Map#size") {
187187
forAll { nem: NonEmptyMap[String, Int] =>
188-
nem.size should ===(nem.toMap.size)
189-
nem.length should ===(nem.toMap.size)
188+
nem.size should ===(nem.toSortedMap.size)
189+
nem.length should ===(nem.toSortedMap.size)
190190
}
191191
}
192192
}

0 commit comments

Comments
 (0)