Repository: gcanti/fp-ts
Pull request #508 (2018-06-28 12:02:31)

Add Group Function for Array
Hi,

I've just added a `group` function for Array.

gcanti: @MaximeRDY is this a porting of https://github.com/purescript/purescript-arrays/blob/7bdd04cef18f63afe8fe0bb59b4180e030e1e0f5/src/Data/Array.purs#L843 ?
MaximeRDY: @gcanti Yes a kind of
gcanti: Ok, then

1) should return an `Array<NonEmptyArray<A>>` so I'd move this function to the `NonEmptyArray` module

2) looks like there's something wrong in the implementation: the following tests (from `purescript-arrays`) fail

```ts
const isOdd = (n: number): boolean => n % 2 === 1

const setoidOdd: Setoid<number> = {
  equals: (x, y) => isOdd(x) && isOdd(y)
}

assert.deepEqual(group(setoidNumber)([1, 1, 2, 2, 1]), [[1, 1], [2, 2], [1]])
assert.deepEqual(group(setoidOdd)([1, 3, 2, 4, 3, 3]), [[1, 3], [2], [4], [3, 3]])
```
MaximeRDY: Ok maybe I've figured why the tests fail. 

The group method work like this:
```
assert.deepEqual(group(setoidNumber)([1, 2, 1, 1, 2]), [[1, 1, 1], [2, 2]])
```

I'm wondering why it should respond like this: 
```
assert.deepEqual(group(setoidNumber)([1, 1, 2, 2, 1]), [[1, 1], [2, 2], [1]])
```
sledorze: Maybe because it groups successive values? (You may look at purescript test/impl)
gcanti: I think that you implemented something more like `group'`

https://github.com/purescript/purescript-arrays/blob/7bdd04cef18f63afe8fe0bb59b4180e030e1e0f5/src/Data/Array.purs#L851

however `group` is more general (`group'` can be derived)
MaximeRDY: @gcanti That make sense :-) 
I'll try to do it today or this week-end. 
Do you have any advice about the naming for `group'` ? 
raveclassic: Such `group` can generalized for any `Filterable`. What about moving to `Filterable.ts`? (similar to `unique` in https://github.com/gcanti/fp-ts/pull/510)
gcanti: > Do you have any advice about the naming for group' ?

mhh actually no.. @sledorze any suggestion?
gcanti: > Such `group` can be generalized for any `Filterable`

Ah, I missed this. @raveclassic how? Could you please elaborate?


raveclassic: Well I missed that there should be a notion of order of Filterable structures for such functions to work generally
sledorze: @gcanti I think the difference between group and group' in purescript is not very explicit.
May we be more explicit with a two word name like: `globalGroup` or `groupSorted` or `groupDistinct`?

(I'm bad at naming)


Patch:
diff --git a/README.md b/README.md
index c9b5c180..40cf8c37 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Functional programming in TypeScript
   </a>
 </p>
 
-Inspired by [PureScript](http://www.purescript.org), [fantasy-land](https://github.com/fantasyland/fantasy-land), [static-land](https://github.com/rpominov/static-land), Scala.
+Inspired by [PureScript](http://www.purescript.org), [static-land](https://github.com/rpominov/static-land), Scala.
 
 The idea (faking higher kinded types in TypeScript) is based on [Lightweight higher-kinded polymorphism](https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-kinded-polymorphism.pdf)
 
diff --git a/docs-generator/code2comment.html b/docs-generator/code2comment.html
index a9b217f1..dde51031 100644
--- a/docs-generator/code2comment.html
+++ b/docs-generator/code2comment.html
@@ -21,7 +21,7 @@
     }
     function t(src) {
       const lines = src.split('\n').map(line => '* ' + line.replace('../src/', 'fp-ts/lib/'))
-      return '*\n* @example\n*\n* ' + lines.join('\n') + '\n*'
+      return '*\n* @example\n' + lines.join('\n') + '\n'
     }
   </script>
 </body>
diff --git a/src/Either.ts b/src/Either.ts
index ca58eddb..f96d4e38 100644
--- a/src/Either.ts
+++ b/src/Either.ts
@@ -15,6 +15,7 @@ import { Compactable2C, Separated } from './Compactable'
 import { Monoid } from './Monoid'
 import { Filterable2C } from './Filterable'
 import { Witherable2C } from './Witherable'
+import { Semigroup } from './Semigroup'
 
 declare module './HKT' {
   interface URI2HKT2<L, A> {
@@ -265,6 +266,60 @@ export const getSetoid = <L, A>(SL: Setoid<L>, SA: Setoid<A>): Setoid<Either<L,
   }
 }
 
+/**
+ * Semigroup returning the left-most non-`Left` value. If both operands are `Right`s then the inner values are
+ * appended using the provided `Semigroup`
+ *
+ * @example
+ * import { semigroupSum } from 'fp-ts/lib/Semigroup'
+ *
+ * const S = getSemigroup<string, number>(semigroupSum)
+ * assert.deepEqual(S.concat(left('a'), left('b')), left('a'))
+ * assert.deepEqual(S.concat(left('a'), right(2)), right(2))
+ * assert.deepEqual(S.concat(right(1), left('b')), right(1))
+ * assert.deepEqual(S.concat(right(1), right(2)), right(3))
+ *
+ * @function
+ * @since 1.7.0
+ */
+export const getSemigroup = <L, A>(S: Semigroup<A>): Semigroup<Either<L, A>> => {
+  return {
+    concat: (x, y) => (y.isLeft() ? x : x.isLeft() ? y : right(S.concat(x.value, y.value)))
+  }
+}
+
+/**
+ * {@link Apply} semigroup
+ *
+ * @example
+ * import { semigroupSum } from 'fp-ts/lib/Semigroup'
+ *
+ * const S = getApplySemigroup<string, number>(semigroupSum)
+ * assert.deepEqual(S.concat(left('a'), left('b')), left('a'))
+ * assert.deepEqual(S.concat(left('a'), right(2)), left('a'))
+ * assert.deepEqual(S.concat(right(1), left('b')), left('b'))
+ * assert.deepEqual(S.concat(right(1), right(2)), right(3))
+ *
+ * @function
+ * @since 1.7.0
+ */
+export const getApplySemigroup = <L, A>(S: Semigroup<A>): Semigroup<Either<L, A>> => {
+  return {
+    concat: (x, y) => (x.isLeft() ? x : y.isLeft() ? y : right(S.concat(x.value, y.value)))
+  }
+}
+
+/**
+ * @function
+ * @since 1.7.0
+ */
+export const getApplyMonoid = <L, A>(M: Monoid<A>): Monoid<Either<L, A>> => {
+  return {
+    ...getApplySemigroup(M),
+    empty: right(M.empty)
+  }
+}
+
 const map = <L, A, B>(fa: Either<L, A>, f: (a: A) => B): Either<L, B> => {
   return fa.map(f)
 }
diff --git a/src/Foldable.ts b/src/Foldable.ts
index fe37ed69..ed118c92 100644
--- a/src/Foldable.ts
+++ b/src/Foldable.ts
@@ -207,8 +207,7 @@ export function foldM<F, M>(
 }
 
 /**
- * Traverse a data structure, performing some effects encoded by an `Applicative` functor at each value, ignoring the
- * final result.
+ * Use {@link traverse}
  */
 export function traverse_<M extends URIS3, F extends URIS>(
   M: Applicative3<M>,
@@ -235,10 +234,10 @@ export function traverse_<M, F>(
   F: Foldable<F>
 ): <A, B>(f: (a: A) => HKT<M, B>, fa: HKT<F, A>) => HKT<M, void>
 /**
- * Traverse a data structure, performing some effects encoded by an `Applicative` functor at each value, ignoring the
- * final result.
+ * Use {@link traverse}
  * @function
  * @since 1.0.0
+ * @deprecated
  */
 export function traverse_<M, F>(
   M: Applicative<M>,
@@ -492,3 +491,45 @@ export function toArray<F>(F: Foldable<F>): <A>(fa: HKT<F, A>) => Array<A>
 export function toArray<F>(F: Foldable<F>): <A>(fa: HKT<F, A>) => Array<A> {
   return fa => foldMap(F, unsafeMonoidArray)(fa, a => [a])
 }
+
+/**
+ * Traverse a data structure, performing some effects encoded by an `Applicative` functor at each value, ignoring the
+ * final result.
+ */
+export function traverse<M extends URIS3, F extends URIS>(
+  M: Applicative3<M>,
+  F: Foldable1<F>
+): <U, L, A, B>(fa: Type<F, A>, f: (a: A) => Type3<M, U, L, B>) => Type3<M, U, L, void>
+export function traverse<M extends URIS3, F extends URIS, U, L>(
+  M: Applicative3C<M, U, L>,
+  F: Foldable1<F>
+): <A, B>(fa: Type<F, A>, f: (a: A) => Type3<M, U, L, B>) => Type3<M, U, L, void>
+export function traverse<M extends URIS2, F extends URIS>(
+  M: Applicative2<M>,
+  F: Foldable1<F>
+): <L, A, B>(fa: Type<F, A>, f: (a: A) => Type2<M, L, B>) => Type2<M, L, void>
+export function traverse<M extends URIS2, F extends URIS, L>(
+  M: Applicative2C<M, L>,
+  F: Foldable1<F>
+): <A, B>(fa: Type<F, A>, f: (a: A) => Type2<M, L, B>) => Type2<M, L, void>
+export function traverse<M extends URIS, F extends URIS>(
+  M: Applicative1<M>,
+  F: Foldable1<F>
+): <A, B>(fa: Type<F, A>, f: (a: A) => Type<M, B>) => Type<M, void>
+export function traverse<M, F>(
+  M: Applicative<M>,
+  F: Foldable<F>
+): <A, B>(fa: HKT<F, A>, f: (a: A) => HKT<M, B>) => HKT<M, void>
+/**
+ * Traverse a data structure, performing some effects encoded by an `Applicative` functor at each value, ignoring the
+ * final result.
+ * @function
+ * @since 1.7.0
+ */
+export function traverse<M, F>(
+  M: Applicative<M>,
+  F: Foldable<F>
+): <A, B>(fa: HKT<F, A>, f: (a: A) => HKT<M, B>) => HKT<M, void> {
+  const traverseMF = traverse_(M, F)
+  return (fa, f) => traverseMF(f, fa)
+}
diff --git a/src/NonEmptyArray.ts b/src/NonEmptyArray.ts
index 9c522595..9aca9d5b 100644
--- a/src/NonEmptyArray.ts
+++ b/src/NonEmptyArray.ts
@@ -8,7 +8,8 @@ import { Option, none, some } from './Option'
 import { Ord } from './Ord'
 import { Semigroup, fold, getJoinSemigroup, getMeetSemigroup } from './Semigroup'
 import { Traversable1 } from './Traversable'
-import { concat as uncurriedConcat, toString } from './function'
+import { concat as uncurriedConcat, toString, compose } from './function'
+import { Setoid } from './Setoid'
 
 declare module './HKT' {
   interface URI2HKT<A> {
@@ -289,6 +290,40 @@ export const getSemigroup = <A = never>(): Semigroup<NonEmptyArray<A>> => {
   return { concat }
 }
 
+/**
+ *  Group equal, consecutive elements of an array into arrays.
+ */
+export const group = <A>(S: Setoid<A>) => (as: Array<A>): Array<NonEmptyArray<A>> => {
+  const r: Array<NonEmptyArray<A>> = []
+  const len = as.length
+  if (len === 0) {
+    return r
+  }
+  let head: A = as[0]
+  let tail: Array<A> = []
+  for (let i = 1; i < len; i++) {
+    const x = as[i]
+    if (S.equals(x, head)) {
+      tail.push(x)
+    } else {
+      r.push(new NonEmptyArray(head, tail))
+      head = x
+      tail = []
+    }
+  }
+  r.push(new NonEmptyArray(head, tail))
+  return r
+}
+
+/**
+ *  Sort and then group the elements of an array into arrays.
+ */
+export const groupSort = <A>(O: Ord<A>): ((as: Array<A>) => Array<NonEmptyArray<A>>) =>
+  compose(
+    group(O),
+    sort(O)
+  )
+
 const reduce = <A, B>(fa: NonEmptyArray<A>, b: B, f: (b: B, a: A) => B): B => {
   return fa.reduce(b, f)
 }
diff --git a/src/Option.ts b/src/Option.ts
index 36cd4333..d1e4b38c 100644
--- a/src/Option.ts
+++ b/src/Option.ts
@@ -402,7 +402,47 @@ const zero = <A>(): Option<A> => {
 }
 
 /**
- * `Option` monoid returning the left-most non-`None` value
+ * {@link Apply} semigroup
+ *
+ * @example
+ * import { semigroupSum } from 'fp-ts/lib/Semigroup'
+ *
+ * const S = getSemigroup(semigroupSum)
+ * assert.deepEqual(S.concat(none, none), none)
+ * assert.deepEqual(S.concat(some(1), none), none)
+ * assert.deepEqual(S.concat(none, some(1)), none)
+ * assert.deepEqual(S.concat(some(1), some(2)), some(3))
+ *
+ * @function
+ * @since 1.7.0
+ */
+export const getApplySemigroup = <A>(S: Semigroup<A>): Semigroup<Option<A>> => {
+  return {
+    concat: (x, y) => (x.isSome() && y.isSome() ? some(S.concat(x.value, y.value)) : none)
+  }
+}
+
+/**
+ * @function
+ * @since 1.7.0
+ */
+export const getApplyMonoid = <A>(M: Monoid<A>): Monoid<Option<A>> => {
+  return {
+    ...getApplySemigroup(M),
+    empty: some(M.empty)
+  }
+}
+
+/**
+ * Monoid returning the left-most non-`None` value
+ *
+ * @example
+ * const M = getFirstMonoid<number>()
+ * assert.deepEqual(M.concat(none, none), none)
+ * assert.deepEqual(M.concat(some(1), none), some(1))
+ * assert.deepEqual(M.concat(none, some(1)), some(1))
+ * assert.deepEqual(M.concat(some(1), some(2)), some(1))
+ *
  * @function
  * @since 1.0.0
  */
@@ -414,7 +454,15 @@ export const getFirstMonoid = <A = never>(): Monoid<Option<A>> => {
 }
 
 /**
- * `Option` monoid returning the right-most non-`None` value
+ * Monoid returning the right-most non-`None` value
+ *
+ * @example
+ * const M = getLastMonoid<number>()
+ * assert.deepEqual(M.concat(none, none), none)
+ * assert.deepEqual(M.concat(some(1), none), some(1))
+ * assert.deepEqual(M.concat(none, some(1)), some(1))
+ * assert.deepEqual(M.concat(some(1), some(2)), some(2))
+ *
  * @function
  * @since 1.0.0
  */
@@ -423,17 +471,16 @@ export const getLastMonoid = <A = never>(): Monoid<Option<A>> => {
 }
 
 /**
- * `Option` monoid returning the left-most non-None value. If both operands are `Some`s then the inner values are
+ * Monoid returning the left-most non-`None` value. If both operands are `Some`s then the inner values are
  * appended using the provided `Semigroup`
  *
  * @example
- * import { none, some, getMonoid } from 'fp-ts/lib/Option'
  * import { semigroupSum } from 'fp-ts/lib/Semigroup'
  *
  * const M = getMonoid(semigroupSum)
  * assert.deepEqual(M.concat(none, none), none)
- * assert.deepEqual(M.concat(none, some(1)), some(1))
  * assert.deepEqual(M.concat(some(1), none), some(1))
+ * assert.deepEqual(M.concat(none, some(1)), some(1))
  * assert.deepEqual(M.concat(some(1), some(2)), some(3))
  *
  * @function
diff --git a/src/StrMap.ts b/src/StrMap.ts
index cc32b948..22928a66 100644
--- a/src/StrMap.ts
+++ b/src/StrMap.ts
@@ -233,7 +233,7 @@ export function fromFoldable<F>(
 export const collect = <A, B>(d: StrMap<A>, f: (k: string, a: A) => B): Array<B> => {
   const out: Array<B> = []
   const value = d.value
-  const keys = Object.keys(value)
+  const keys = Object.keys(value).sort()
   for (const key of keys) {
     out.push(f(key, d.value[key]))
   }
diff --git a/src/Task.ts b/src/Task.ts
index cb5bf0b7..a8943629 100644
--- a/src/Task.ts
+++ b/src/Task.ts
@@ -145,6 +145,21 @@ export const fromIO = <A>(io: IO<A>): Task<A> => {
   return new Task(() => Promise.resolve(io.run()))
 }
 
+/**
+ * @function
+ * @since 1.7.0
+ */
+export const delay = <A>(millis: number, a: A): Task<A> => {
+  return new Task(
+    () =>
+      new Promise(resolve => {
+        setTimeout(() => {
+          resolve(a)
+        }, millis)
+      })
+  )
+}
+
 /**
  * @instance
  * @since 1.0.0
diff --git a/type-classes.dot b/type-classes.dot
index 0e630cc2..acb71d7e 100644
--- a/type-classes.dot
+++ b/type-classes.dot
@@ -12,7 +12,7 @@ digraph G {
   node [style=filled,color=black,fillcolor="#FDF4AA"];
   "Category" -> "Semigroupoid"
   node [style=filled,color=black,fillcolor="#659DFE"];
-  "Functor" "Applicative" "Monad" "Alternative" "Traversable" "Foldable"
+  "Functor" "Applicative" "Monad" "Alternative" "Traversable" "Foldable" "Compactable"
   node [style=filled,color=black,fillcolor="#BFD7FF"];
   "Alt" -> "Functor"
   "Alternative" -> "Applicative"
@@ -23,6 +23,10 @@ digraph G {
   "Comonad" -> "Extend" -> "Functor"
   "Traversable" -> "Foldable"
   "Traversable" -> "Functor"
+  "Filterable" -> "Functor"
+  "Filterable" -> "Compactable"
+  "Witherable" -> "Traversable"
+  "Witherable" -> "Filterable"
   node [style=filled,color=black,fillcolor="#FDF4AA"];
   "BooleanAlgebra" -> "HeytingAlgebra" -> "BoundedDistributiveLattice" -> "BoundedLattice" -> "BoundedJoinSemilattice"
   "BoundedDistributiveLattice" -> "DistributiveLattice" -> "Lattice" -> "JoinSemilattice"
diff --git a/type-classes.svg b/type-classes.svg
index 0a789cfa..20f81e36 100644
--- a/type-classes.svg
+++ b/type-classes.svg
@@ -1,7 +1,7 @@
-<svg width="1618pt" height="404pt" viewBox="0.00 0.00 1618.00 404.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="1647pt" height="404pt" viewBox="0.00 0.00 1647.00 404.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 400)">
 <title>G</title>
-<polygon fill="white" stroke="white" points="-4,5 -4,-400 1615,-400 1615,5 -4,5"></polygon>
+<polygon fill="white" stroke="white" points="-4,5 -4,-400 1644,-400 1644,5 -4,5"></polygon>
 <!-- Monoid -->
 <g id="node1" class="node"><title>Monoid</title>
 <ellipse fill="#fc81bf" stroke="black" cx="57" cy="-18" rx="42.8926" ry="18"></ellipse>
@@ -84,243 +84,278 @@
 </g>
 <!-- Functor -->
 <g id="node15" class="node"><title>Functor</title>
-<ellipse fill="#659dfe" stroke="black" cx="722" cy="-234" rx="43.5367" ry="18"></ellipse>
-<text text-anchor="middle" x="722" y="-229.8" font-family="arial" font-size="14.00">Functor</text>
+<ellipse fill="#659dfe" stroke="black" cx="758" cy="-234" rx="43.5367" ry="18"></ellipse>
+<text text-anchor="middle" x="758" y="-229.8" font-family="arial" font-size="14.00">Functor</text>
 </g>
 <!-- Applicative -->
 <g id="node16" class="node"><title>Applicative</title>
-<ellipse fill="#659dfe" stroke="black" cx="619" cy="-90" rx="57.9391" ry="18"></ellipse>
-<text text-anchor="middle" x="619" y="-85.8" font-family="arial" font-size="14.00">Applicative</text>
+<ellipse fill="#659dfe" stroke="black" cx="782" cy="-90" rx="57.9391" ry="18"></ellipse>
+<text text-anchor="middle" x="782" y="-85.8" font-family="arial" font-size="14.00">Applicative</text>
 </g>
 <!-- Apply -->
-<g id="node27" class="node"><title>Apply</title>
-<ellipse fill="#bfd7ff" stroke="black" cx="675" cy="-162" rx="35.3703" ry="18"></ellipse>
-<text text-anchor="middle" x="675" y="-157.8" font-family="arial" font-size="14.00">Apply</text>
+<g id="node28" class="node"><title>Apply</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="804" cy="-162" rx="35.3703" ry="18"></ellipse>
+<text text-anchor="middle" x="804" y="-157.8" font-family="arial" font-size="14.00">Apply</text>
 </g>
 <!-- Applicative&#45;&gt;Apply -->
 <g id="edge20" class="edge"><title>Applicative-&gt;Apply</title>
-<path fill="none" stroke="black" d="M632.271,-107.589C639.276,-116.345 647.999,-127.249 655.734,-136.918"></path>
-<polygon fill="black" stroke="black" points="653.229,-139.39 662.21,-145.012 658.696,-135.017 653.229,-139.39"></polygon>
+<path fill="none" stroke="black" d="M787.326,-107.945C789.775,-115.739 792.742,-125.178 795.489,-133.921"></path>
+<polygon fill="black" stroke="black" points="792.233,-135.234 798.571,-143.725 798.911,-133.135 792.233,-135.234"></polygon>
 </g>
 <!-- Monad -->
 <g id="node17" class="node"><title>Monad</title>
-<ellipse fill="#659dfe" stroke="black" cx="628" cy="-18" rx="40.606" ry="18"></ellipse>
-<text text-anchor="middle" x="628" y="-13.8" font-family="arial" font-size="14.00">Monad</text>
+<ellipse fill="#659dfe" stroke="black" cx="791" cy="-18" rx="40.606" ry="18"></ellipse>
+<text text-anchor="middle" x="791" y="-13.8" font-family="arial" font-size="14.00">Monad</text>
 </g>
 <!-- Monad&#45;&gt;Applicative -->
 <g id="edge19" class="edge"><title>Monad-&gt;Applicative</title>
-<path fill="none" stroke="black" d="M625.775,-36.3034C624.783,-44.0173 623.592,-53.2875 622.486,-61.8876"></path>
-<polygon fill="black" stroke="black" points="619.003,-61.531 621.199,-71.8957 625.946,-62.4237 619.003,-61.531"></polygon>
+<path fill="none" stroke="black" d="M788.775,-36.3034C787.783,-44.0173 786.592,-53.2875 785.486,-61.8876"></path>
+<polygon fill="black" stroke="black" points="782.003,-61.531 784.199,-71.8957 788.946,-62.4237 782.003,-61.531"></polygon>
 </g>
 <!-- Chain -->
-<g id="node29" class="node"><title>Chain</title>
-<ellipse fill="#bfd7ff" stroke="black" cx="731" cy="-90" rx="36.0129" ry="18"></ellipse>
-<text text-anchor="middle" x="731" y="-85.8" font-family="arial" font-size="14.00">Chain</text>
+<g id="node30" class="node"><title>Chain</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="894" cy="-90" rx="36.0129" ry="18"></ellipse>
+<text text-anchor="middle" x="894" y="-85.8" font-family="arial" font-size="14.00">Chain</text>
 </g>
 <!-- Monad&#45;&gt;Chain -->
 <g id="edge23" class="edge"><title>Monad-&gt;Chain</title>
-<path fill="none" stroke="black" d="M649.342,-33.504C664.596,-43.8709 685.3,-57.9418 702.044,-69.3209"></path>
-<polygon fill="black" stroke="black" points="700.15,-72.266 710.389,-74.9922 704.085,-66.4765 700.15,-72.266"></polygon>
+<path fill="none" stroke="black" d="M812.342,-33.504C827.596,-43.8709 848.3,-57.9418 865.044,-69.3209"></path>
+<polygon fill="black" stroke="black" points="863.15,-72.266 873.389,-74.9922 867.085,-66.4765 863.15,-72.266"></polygon>
 </g>
 <!-- Alternative -->
 <g id="node18" class="node"><title>Alternative</title>
-<ellipse fill="#659dfe" stroke="black" cx="513" cy="-18" rx="56.7929" ry="18"></ellipse>
-<text text-anchor="middle" x="513" y="-13.8" font-family="arial" font-size="14.00">Alternative</text>
+<ellipse fill="#659dfe" stroke="black" cx="676" cy="-18" rx="56.7929" ry="18"></ellipse>
+<text text-anchor="middle" x="676" y="-13.8" font-family="arial" font-size="14.00">Alternative</text>
 </g>
 <!-- Alternative&#45;&gt;Applicative -->
 <g id="edge14" class="edge"><title>Alternative-&gt;Applicative</title>
-<path fill="none" stroke="black" d="M536.525,-34.5353C551.346,-44.3229 570.677,-57.0884 586.898,-67.8003"></path>
-<polygon fill="black" stroke="black" points="585.268,-70.9181 595.541,-73.5082 589.125,-65.0769 585.268,-70.9181"></polygon>
+<path fill="none" stroke="black" d="M699.525,-34.5353C714.346,-44.3229 733.677,-57.0884 749.898,-67.8003"></path>
+<polygon fill="black" stroke="black" points="748.268,-70.9181 758.541,-73.5082 752.125,-65.0769 748.268,-70.9181"></polygon>
 </g>
 <!-- Plus -->
-<g id="node25" class="node"><title>Plus</title>
-<ellipse fill="#bfd7ff" stroke="black" cx="513" cy="-90" rx="29.6339" ry="18"></ellipse>
-<text text-anchor="middle" x="513" y="-85.8" font-family="arial" font-size="14.00">Plus</text>
+<g id="node26" class="node"><title>Plus</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="676" cy="-90" rx="29.6339" ry="18"></ellipse>
+<text text-anchor="middle" x="676" y="-85.8" font-family="arial" font-size="14.00">Plus</text>
 </g>
 <!-- Alternative&#45;&gt;Plus -->
 <g id="edge16" class="edge"><title>Alternative-&gt;Plus</title>
-<path fill="none" stroke="black" d="M513,-36.3034C513,-44.0173 513,-53.2875 513,-61.8876"></path>
-<polygon fill="black" stroke="black" points="509.5,-61.8956 513,-71.8957 516.5,-61.8957 509.5,-61.8956"></polygon>
+<path fill="none" stroke="black" d="M676,-36.3034C676,-44.0173 676,-53.2875 676,-61.8876"></path>
+<polygon fill="black" stroke="black" points="672.5,-61.8956 676,-71.8957 679.5,-61.8957 672.5,-61.8956"></polygon>
 </g>
 <!-- Traversable -->
 <g id="node19" class="node"><title>Traversable</title>
-<ellipse fill="#659dfe" stroke="black" cx="890" cy="-162" rx="62.0137" ry="18"></ellipse>
-<text text-anchor="middle" x="890" y="-157.8" font-family="arial" font-size="14.00">Traversable</text>
+<ellipse fill="#659dfe" stroke="black" cx="497" cy="-162" rx="62.0137" ry="18"></ellipse>
+<text text-anchor="middle" x="497" y="-157.8" font-family="arial" font-size="14.00">Traversable</text>
 </g>
 <!-- Traversable&#45;&gt;Functor -->
 <g id="edge33" class="edge"><title>Traversable-&gt;Functor</title>
-<path fill="none" stroke="black" d="M856.003,-177.166C828.437,-188.651 789.577,-204.843 760.798,-216.834"></path>
-<polygon fill="black" stroke="black" points="759.34,-213.65 751.456,-220.727 762.033,-220.111 759.34,-213.65"></polygon>
+<path fill="none" stroke="black" d="M543.234,-174.075C585.312,-184.335 649.062,-200.332 704,-216 707.615,-217.031 711.356,-218.134 715.103,-219.263"></path>
+<polygon fill="black" stroke="black" points="714.372,-222.7 724.959,-222.286 716.424,-216.007 714.372,-222.7"></polygon>
 </g>
 <!-- Foldable -->
 <g id="node20" class="node"><title>Foldable</title>
-<ellipse fill="#659dfe" stroke="black" cx="890" cy="-234" rx="48.1264" ry="18"></ellipse>
-<text text-anchor="middle" x="890" y="-229.8" font-family="arial" font-size="14.00">Foldable</text>
+<ellipse fill="#659dfe" stroke="black" cx="494" cy="-234" rx="48.1264" ry="18"></ellipse>
+<text text-anchor="middle" x="494" y="-229.8" font-family="arial" font-size="14.00">Foldable</text>
 </g>
 <!-- Traversable&#45;&gt;Foldable -->
 <g id="edge31" class="edge"><title>Traversable-&gt;Foldable</title>
-<path fill="none" stroke="black" d="M890,-180.303C890,-188.017 890,-197.288 890,-205.888"></path>
-<polygon fill="black" stroke="black" points="886.5,-205.896 890,-215.896 893.5,-205.896 886.5,-205.896"></polygon>
+<path fill="none" stroke="black" d="M496.258,-180.303C495.928,-188.017 495.531,-197.288 495.162,-205.888"></path>
+<polygon fill="black" stroke="black" points="491.665,-205.755 494.733,-215.896 498.658,-206.055 491.665,-205.755"></polygon>
+</g>
+<!-- Compactable -->
+<g id="node21" class="node"><title>Compactable</title>
+<ellipse fill="#659dfe" stroke="black" cx="628" cy="-234" rx="67.8319" ry="18"></ellipse>
+<text text-anchor="middle" x="628" y="-229.8" font-family="arial" font-size="14.00">Compactable</text>
 </g>
 <!-- Alt -->
-<g id="node21" class="node"><title>Alt</title>
-<ellipse fill="#bfd7ff" stroke="black" cx="554" cy="-162" rx="27" ry="18"></ellipse>
-<text text-anchor="middle" x="554" y="-157.8" font-family="arial" font-size="14.00">Alt</text>
+<g id="node22" class="node"><title>Alt</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="724" cy="-162" rx="27" ry="18"></ellipse>
+<text text-anchor="middle" x="724" y="-157.8" font-family="arial" font-size="14.00">Alt</text>
 </g>
 <!-- Alt&#45;&gt;Functor -->
 <g id="edge12" class="edge"><title>Alt-&gt;Functor</title>
-<path fill="none" stroke="black" d="M576.309,-172.295C603.524,-183.635 649.992,-202.997 683.131,-216.805"></path>
-<polygon fill="black" stroke="black" points="681.947,-220.103 692.524,-220.718 684.639,-213.641 681.947,-220.103"></polygon>
+<path fill="none" stroke="black" d="M731.886,-179.235C735.846,-187.389 740.743,-197.471 745.223,-206.693"></path>
+<polygon fill="black" stroke="black" points="742.165,-208.41 749.683,-215.876 748.462,-205.352 742.165,-208.41"></polygon>
 </g>
 <!-- Plus&#45;&gt;Alt -->
 <g id="edge17" class="edge"><title>Plus-&gt;Alt</title>
-<path fill="none" stroke="black" d="M522.509,-107.235C527.529,-115.805 533.796,-126.506 539.415,-136.1"></path>
-<polygon fill="black" stroke="black" points="536.468,-137.993 544.542,-144.853 542.508,-134.455 536.468,-137.993"></polygon>
+<path fill="none" stroke="black" d="M686.892,-106.884C692.968,-115.745 700.66,-126.963 707.464,-136.885"></path>
+<polygon fill="black" stroke="black" points="704.609,-138.911 713.151,-145.179 710.382,-134.952 704.609,-138.911"></polygon>
 </g>
 <!-- Apply&#45;&gt;Functor -->
 <g id="edge21" class="edge"><title>Apply-&gt;Functor</title>
-<path fill="none" stroke="black" d="M685.901,-179.235C691.631,-187.77 698.781,-198.418 705.201,-207.981"></path>
-<polygon fill="black" stroke="black" points="702.352,-210.015 710.832,-216.367 708.163,-206.113 702.352,-210.015"></polygon>
+<path fill="none" stroke="black" d="M793.331,-179.235C787.723,-187.77 780.725,-198.418 774.441,-207.981"></path>
+<polygon fill="black" stroke="black" points="771.497,-206.087 768.931,-216.367 777.347,-209.932 771.497,-206.087"></polygon>
 </g>
 <!-- Chain&#45;&gt;Apply -->
 <g id="edge24" class="edge"><title>Chain-&gt;Apply</title>
-<path fill="none" stroke="black" d="M718.293,-106.884C711.133,-115.834 702.048,-127.19 694.052,-137.185"></path>
-<polygon fill="black" stroke="black" points="691.171,-135.184 687.657,-145.179 696.637,-139.557 691.171,-135.184"></polygon>
+<path fill="none" stroke="black" d="M875.352,-105.504C862.44,-115.547 845.059,-129.066 830.684,-140.246"></path>
+<polygon fill="black" stroke="black" points="828.369,-137.612 822.624,-146.515 832.667,-143.138 828.369,-137.612"></polygon>
 </g>
 <!-- ChainRec -->
-<g id="node30" class="node"><title>ChainRec</title>
-<ellipse fill="#bfd7ff" stroke="black" cx="740" cy="-18" rx="53.3476" ry="18"></ellipse>
-<text text-anchor="middle" x="740" y="-13.8" font-family="arial" font-size="14.00">ChainRec</text>
+<g id="node31" class="node"><title>ChainRec</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="903" cy="-18" rx="53.3476" ry="18"></ellipse>
+<text text-anchor="middle" x="903" y="-13.8" font-family="arial" font-size="14.00">ChainRec</text>
 </g>
 <!-- ChainRec&#45;&gt;Chain -->
 <g id="edge26" class="edge"><title>ChainRec-&gt;Chain</title>
-<path fill="none" stroke="black" d="M737.775,-36.3034C736.783,-44.0173 735.592,-53.2875 734.486,-61.8876"></path>
-<polygon fill="black" stroke="black" points="731.003,-61.531 733.199,-71.8957 737.946,-62.4237 731.003,-61.531"></polygon>
+<path fill="none" stroke="black" d="M900.775,-36.3034C899.783,-44.0173 898.592,-53.2875 897.486,-61.8876"></path>
+<polygon fill="black" stroke="black" points="894.003,-61.531 896.199,-71.8957 900.946,-62.4237 894.003,-61.531"></polygon>
 </g>
 <!-- Comonad -->
-<g id="node32" class="node"><title>Comonad</title>
-<ellipse fill="#bfd7ff" stroke="black" cx="838" cy="-90" rx="52.7854" ry="18"></ellipse>
-<text text-anchor="middle" x="838" y="-85.8" font-family="arial" font-size="14.00">Comonad</text>
+<g id="node33" class="node"><title>Comonad</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="1001" cy="-90" rx="52.7854" ry="18"></ellipse>
+<text text-anchor="middle" x="1001" y="-85.8" font-family="arial" font-size="14.00">Comonad</text>
 </g>
 <!-- Extend -->
-<g id="node34" class="node"><title>Extend</title>
-<ellipse fill="#bfd7ff" stroke="black" cx="769" cy="-162" rx="41.1877" ry="18"></ellipse>
-<text text-anchor="middle" x="769" y="-157.8" font-family="arial" font-size="14.00">Extend</text>
+<g id="node35" class="node"><title>Extend</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="960" cy="-162" rx="41.1877" ry="18"></ellipse>
+<text text-anchor="middle" x="960" y="-157.8" font-family="arial" font-size="14.00">Extend</text>
 </g>
 <!-- Comonad&#45;&gt;Extend -->
 <g id="edge28" class="edge"><title>Comonad-&gt;Extend</title>
-<path fill="none" stroke="black" d="M821.997,-107.235C813.114,-116.247 801.908,-127.615 792.091,-137.574"></path>
-<polygon fill="black" stroke="black" points="789.444,-135.274 784.917,-144.853 794.429,-140.188 789.444,-135.274"></polygon>
+<path fill="none" stroke="black" d="M991.075,-107.945C986.24,-116.199 980.325,-126.299 974.958,-135.462"></path>
+<polygon fill="black" stroke="black" points="971.868,-133.813 969.834,-144.211 977.908,-137.351 971.868,-133.813"></polygon>
 </g>
 <!-- Extend&#45;&gt;Functor -->
 <g id="edge29" class="edge"><title>Extend-&gt;Functor</title>
-<path fill="none" stroke="black" d="M757.862,-179.589C752.125,-188.132 745.016,-198.722 738.643,-208.213"></path>
-<polygon fill="black" stroke="black" points="735.727,-206.277 733.058,-216.53 741.539,-210.179 735.727,-206.277"></polygon>
+<path fill="none" stroke="black" d="M928.88,-173.784C894.339,-185.754 838.411,-205.135 800.006,-218.444"></path>
+<polygon fill="black" stroke="black" points="798.46,-215.275 790.158,-221.856 800.752,-221.889 798.46,-215.275"></polygon>
+</g>
+<!-- Filterable -->
+<g id="node38" class="node"><title>Filterable</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="628" cy="-162" rx="50.9735" ry="18"></ellipse>
+<text text-anchor="middle" x="628" y="-157.8" font-family="arial" font-size="14.00">Filterable</text>
+</g>
+<!-- Filterable&#45;&gt;Functor -->
+<g id="edge35" class="edge"><title>Filterable-&gt;Functor</title>
+<path fill="none" stroke="black" d="M654.621,-177.334C674.511,-188.044 701.869,-202.776 723.446,-214.394"></path>
+<polygon fill="black" stroke="black" points="721.836,-217.502 732.3,-219.162 725.155,-211.339 721.836,-217.502"></polygon>
+</g>
+<!-- Filterable&#45;&gt;Compactable -->
+<g id="edge37" class="edge"><title>Filterable-&gt;Compactable</title>
+<path fill="none" stroke="black" d="M628,-180.303C628,-188.017 628,-197.288 628,-205.888"></path>
+<polygon fill="black" stroke="black" points="624.5,-205.896 628,-215.896 631.5,-205.896 624.5,-205.896"></polygon>
+</g>
+<!-- Witherable -->
+<g id="node41" class="node"><title>Witherable</title>
+<ellipse fill="#bfd7ff" stroke="black" cx="534" cy="-90" rx="57.3553" ry="18"></ellipse>
+<text text-anchor="middle" x="534" y="-85.8" font-family="arial" font-size="14.00">Witherable</text>
+</g>
+<!-- Witherable&#45;&gt;Traversable -->
+<g id="edge39" class="edge"><title>Witherable-&gt;Traversable</title>
+<path fill="none" stroke="black" d="M525.043,-107.945C520.789,-115.993 515.608,-125.795 510.862,-134.774"></path>
+<polygon fill="black" stroke="black" points="507.71,-133.248 506.131,-143.725 513.899,-136.519 507.71,-133.248"></polygon>
+</g>
+<!-- Witherable&#45;&gt;Filterable -->
+<g id="edge41" class="edge"><title>Witherable-&gt;Filterable</title>
+<path fill="none" stroke="black" d="M555.33,-106.884C568.159,-116.438 584.67,-128.733 598.71,-139.188"></path>
+<polygon fill="black" stroke="black" points="596.967,-142.254 607.078,-145.42 601.148,-136.64 596.967,-142.254"></polygon>
 </g>
 <!-- BooleanAlgebra -->
-<g id="node37" class="node"><title>BooleanAlgebra</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1174" cy="-18" rx="79.965" ry="18"></ellipse>
-<text text-anchor="middle" x="1174" y="-13.8" font-family="arial" font-size="14.00">BooleanAlgebra</text>
+<g id="node44" class="node"><title>BooleanAlgebra</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1189" cy="-18" rx="79.965" ry="18"></ellipse>
+<text text-anchor="middle" x="1189" y="-13.8" font-family="arial" font-size="14.00">BooleanAlgebra</text>
 </g>
 <!-- HeytingAlgebra -->
-<g id="node39" class="node"><title>HeytingAlgebra</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1174" cy="-90" rx="77.0777" ry="18"></ellipse>
-<text text-anchor="middle" x="1174" y="-85.8" font-family="arial" font-size="14.00">HeytingAlgebra</text>
+<g id="node46" class="node"><title>HeytingAlgebra</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1189" cy="-90" rx="77.0777" ry="18"></ellipse>
+<text text-anchor="middle" x="1189" y="-85.8" font-family="arial" font-size="14.00">HeytingAlgebra</text>
 </g>
 <!-- BooleanAlgebra&#45;&gt;HeytingAlgebra -->
-<g id="edge35" class="edge"><title>BooleanAlgebra-&gt;HeytingAlgebra</title>
-<path fill="none" stroke="black" d="M1174,-36.3034C1174,-44.0173 1174,-53.2875 1174,-61.8876"></path>
-<polygon fill="black" stroke="black" points="1170.5,-61.8956 1174,-71.8957 1177.5,-61.8957 1170.5,-61.8956"></polygon>
+<g id="edge43" class="edge"><title>BooleanAlgebra-&gt;HeytingAlgebra</title>
+<path fill="none" stroke="black" d="M1189,-36.3034C1189,-44.0173 1189,-53.2875 1189,-61.8876"></path>
+<polygon fill="black" stroke="black" points="1185.5,-61.8956 1189,-71.8957 1192.5,-61.8957 1185.5,-61.8956"></polygon>
 </g>
 <!-- BoundedDistributiveLattice -->
-<g id="node40" class="node"><title>BoundedDistributiveLattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1174" cy="-162" rx="125.748" ry="18"></ellipse>
-<text text-anchor="middle" x="1174" y="-157.8" font-family="arial" font-size="14.00">BoundedDistributiveLattice</text>
+<g id="node47" class="node"><title>BoundedDistributiveLattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1189" cy="-162" rx="125.748" ry="18"></ellipse>
+<text text-anchor="middle" x="1189" y="-157.8" font-family="arial" font-size="14.00">BoundedDistributiveLattice</text>
 </g>
 <!-- HeytingAlgebra&#45;&gt;BoundedDistributiveLattice -->
-<g id="edge36" class="edge"><title>HeytingAlgebra-&gt;BoundedDistributiveLattice</title>
-<path fill="none" stroke="black" d="M1174,-108.303C1174,-116.017 1174,-125.288 1174,-133.888"></path>
-<polygon fill="black" stroke="black" points="1170.5,-133.896 1174,-143.896 1177.5,-133.896 1170.5,-133.896"></polygon>
+<g id="edge44" class="edge"><title>HeytingAlgebra-&gt;BoundedDistributiveLattice</title>
+<path fill="none" stroke="black" d="M1189,-108.303C1189,-116.017 1189,-125.288 1189,-133.888"></path>
+<polygon fill="black" stroke="black" points="1185.5,-133.896 1189,-143.896 1192.5,-133.896 1185.5,-133.896"></polygon>
 </g>
 <!-- BoundedLattice -->
-<g id="node41" class="node"><title>BoundedLattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1252" cy="-234" rx="78.2603" ry="18"></ellipse>
-<text text-anchor="middle" x="1252" y="-229.8" font-family="arial" font-size="14.00">BoundedLattice</text>
+<g id="node48" class="node"><title>BoundedLattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1280" cy="-234" rx="78.2603" ry="18"></ellipse>
+<text text-anchor="middle" x="1280" y="-229.8" font-family="arial" font-size="14.00">BoundedLattice</text>
 </g>
 <!-- BoundedDistributiveLattice&#45;&gt;BoundedLattice -->
-<g id="edge37" class="edge"><title>BoundedDistributiveLattice-&gt;BoundedLattice</title>
-<path fill="none" stroke="black" d="M1192.88,-179.945C1202.82,-188.866 1215.16,-199.943 1226,-209.664"></path>
-<polygon fill="black" stroke="black" points="1223.78,-212.378 1233.56,-216.453 1228.46,-207.169 1223.78,-212.378"></polygon>
+<g id="edge45" class="edge"><title>BoundedDistributiveLattice-&gt;BoundedLattice</title>
+<path fill="none" stroke="black" d="M1211.03,-179.945C1222.85,-189.04 1237.59,-200.374 1250.4,-210.229"></path>
+<polygon fill="black" stroke="black" points="1248.43,-213.13 1258.49,-216.453 1252.7,-207.581 1248.43,-213.13"></polygon>
 </g>
 <!-- DistributiveLattice -->
-<g id="node44" class="node"><title>DistributiveLattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1069" cy="-234" rx="87.4486" ry="18"></ellipse>
-<text text-anchor="middle" x="1069" y="-229.8" font-family="arial" font-size="14.00">DistributiveLattice</text>
+<g id="node51" class="node"><title>DistributiveLattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1097" cy="-234" rx="87.4486" ry="18"></ellipse>
+<text text-anchor="middle" x="1097" y="-229.8" font-family="arial" font-size="14.00">DistributiveLattice</text>
 </g>
 <!-- BoundedDistributiveLattice&#45;&gt;DistributiveLattice -->
-<g id="edge40" class="edge"><title>BoundedDistributiveLattice-&gt;DistributiveLattice</title>
-<path fill="none" stroke="black" d="M1148.85,-179.767C1134.85,-189.099 1117.26,-200.83 1102.15,-210.903"></path>
-<polygon fill="black" stroke="black" points="1099.96,-208.152 1093.58,-216.612 1103.84,-213.977 1099.96,-208.152"></polygon>
+<g id="edge48" class="edge"><title>BoundedDistributiveLattice-&gt;DistributiveLattice</title>
+<path fill="none" stroke="black" d="M1166.73,-179.945C1154.78,-189.04 1139.88,-200.374 1126.93,-210.229"></path>
+<polygon fill="black" stroke="black" points="1124.59,-207.612 1118.75,-216.453 1128.83,-213.183 1124.59,-207.612"></polygon>
 </g>
 <!-- BoundedJoinSemilattice -->
-<g id="node42" class="node"><title>BoundedJoinSemilattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1241" cy="-306" rx="114.715" ry="18"></ellipse>
-<text text-anchor="middle" x="1241" y="-301.8" font-family="arial" font-size="14.00">BoundedJoinSemilattice</text>
+<g id="node49" class="node"><title>BoundedJoinSemilattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1269" cy="-306" rx="114.715" ry="18"></ellipse>
+<text text-anchor="middle" x="1269" y="-301.8" font-family="arial" font-size="14.00">BoundedJoinSemilattice</text>
 </g>
 <!-- BoundedLattice&#45;&gt;BoundedJoinSemilattice -->
-<g id="edge38" class="edge"><title>BoundedLattice-&gt;BoundedJoinSemilattice</title>
-<path fill="none" stroke="black" d="M1249.28,-252.303C1248.07,-260.017 1246.61,-269.288 1245.26,-277.888"></path>
-<polygon fill="black" stroke="black" points="1241.78,-277.474 1243.69,-287.896 1248.7,-278.56 1241.78,-277.474"></polygon>
+<g id="edge46" class="edge"><title>BoundedLattice-&gt;BoundedJoinSemilattice</title>
+<path fill="none" stroke="black" d="M1277.28,-252.303C1276.07,-260.017 1274.61,-269.288 1273.26,-277.888"></path>
+<polygon fill="black" stroke="black" points="1269.78,-277.474 1271.69,-287.896 1276.7,-278.56 1269.78,-277.474"></polygon>
 </g>
 <!-- BoundedMeetSemilattice -->
-<g id="node51" class="node"><title>BoundedMeetSemilattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1492" cy="-306" rx="118.226" ry="18"></ellipse>
-<text text-anchor="middle" x="1492" y="-301.8" font-family="arial" font-size="14.00">BoundedMeetSemilattice</text>
+<g id="node58" class="node"><title>BoundedMeetSemilattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1520" cy="-306" rx="118.226" ry="18"></ellipse>
+<text text-anchor="middle" x="1520" y="-301.8" font-family="arial" font-size="14.00">BoundedMeetSemilattice</text>
 </g>
 <!-- BoundedLattice&#45;&gt;BoundedMeetSemilattice -->
-<g id="edge48" class="edge"><title>BoundedLattice-&gt;BoundedMeetSemilattice</title>
-<path fill="none" stroke="black" d="M1298.56,-248.58C1336.04,-259.512 1389.05,-274.973 1430.1,-286.947"></path>
-<polygon fill="black" stroke="black" points="1429.15,-290.316 1439.73,-289.756 1431.11,-283.596 1429.15,-290.316"></polygon>
+<g id="edge56" class="edge"><title>BoundedLattice-&gt;BoundedMeetSemilattice</title>
+<path fill="none" stroke="black" d="M1326.56,-248.58C1364.04,-259.512 1417.05,-274.973 1458.1,-286.947"></path>
+<polygon fill="black" stroke="black" points="1457.15,-290.316 1467.73,-289.756 1459.11,-283.596 1457.15,-290.316"></polygon>
 </g>
 <!-- JoinSemilattice -->
-<g id="node46" class="node"><title>JoinSemilattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1155" cy="-378" rx="75.9145" ry="18"></ellipse>
-<text text-anchor="middle" x="1155" y="-373.8" font-family="arial" font-size="14.00">JoinSemilattice</text>
+<g id="node53" class="node"><title>JoinSemilattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1183" cy="-378" rx="75.9145" ry="18"></ellipse>
+<text text-anchor="middle" x="1183" y="-373.8" font-family="arial" font-size="14.00">JoinSemilattice</text>
 </g>
 <!-- BoundedJoinSemilattice&#45;&gt;JoinSemilattice -->
-<g id="edge46" class="edge"><title>BoundedJoinSemilattice-&gt;JoinSemilattice</title>
-<path fill="none" stroke="black" d="M1220.18,-323.945C1209.11,-332.953 1195.35,-344.158 1183.32,-353.947"></path>
-<polygon fill="black" stroke="black" points="1180.88,-351.425 1175.33,-360.453 1185.29,-356.854 1180.88,-351.425"></polygon>
+<g id="edge54" class="edge"><title>BoundedJoinSemilattice-&gt;JoinSemilattice</title>
+<path fill="none" stroke="black" d="M1248.18,-323.945C1237.11,-332.953 1223.35,-344.158 1211.32,-353.947"></path>
+<polygon fill="black" stroke="black" points="1208.88,-351.425 1203.33,-360.453 1213.29,-356.854 1208.88,-351.425"></polygon>
 </g>
 <!-- Lattice -->
-<g id="node45" class="node"><title>Lattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1069" cy="-306" rx="39.4602" ry="18"></ellipse>
-<text text-anchor="middle" x="1069" y="-301.8" font-family="arial" font-size="14.00">Lattice</text>
+<g id="node52" class="node"><title>Lattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1097" cy="-306" rx="39.4602" ry="18"></ellipse>
+<text text-anchor="middle" x="1097" y="-301.8" font-family="arial" font-size="14.00">Lattice</text>
 </g>
 <!-- DistributiveLattice&#45;&gt;Lattice -->
-<g id="edge41" class="edge"><title>DistributiveLattice-&gt;Lattice</title>
-<path fill="none" stroke="black" d="M1069,-252.303C1069,-260.017 1069,-269.288 1069,-277.888"></path>
-<polygon fill="black" stroke="black" points="1065.5,-277.896 1069,-287.896 1072.5,-277.896 1065.5,-277.896"></polygon>
+<g id="edge49" class="edge"><title>DistributiveLattice-&gt;Lattice</title>
+<path fill="none" stroke="black" d="M1097,-252.303C1097,-260.017 1097,-269.288 1097,-277.888"></path>
+<polygon fill="black" stroke="black" points="1093.5,-277.896 1097,-287.896 1100.5,-277.896 1093.5,-277.896"></polygon>
 </g>
 <!-- Lattice&#45;&gt;JoinSemilattice -->
-<g id="edge42" class="edge"><title>Lattice-&gt;JoinSemilattice</title>
-<path fill="none" stroke="black" d="M1087.66,-322.189C1099.09,-331.491 1113.94,-343.576 1126.78,-354.031"></path>
-<polygon fill="black" stroke="black" points="1124.91,-357.022 1134.88,-360.62 1129.33,-351.593 1124.91,-357.022"></polygon>
+<g id="edge50" class="edge"><title>Lattice-&gt;JoinSemilattice</title>
+<path fill="none" stroke="black" d="M1115.66,-322.189C1127.09,-331.491 1141.94,-343.576 1154.78,-354.031"></path>
+<polygon fill="black" stroke="black" points="1152.91,-357.022 1162.88,-360.62 1157.33,-351.593 1152.91,-357.022"></polygon>
 </g>
 <!-- MeetSemilattice -->
-<g id="node48" class="node"><title>MeetSemilattice</title>
-<ellipse fill="#fdf4aa" stroke="black" cx="1410" cy="-378" rx="79.9262" ry="18"></ellipse>
-<text text-anchor="middle" x="1410" y="-373.8" font-family="arial" font-size="14.00">MeetSemilattice</text>
+<g id="node55" class="node"><title>MeetSemilattice</title>
+<ellipse fill="#fdf4aa" stroke="black" cx="1438" cy="-378" rx="79.9262" ry="18"></ellipse>
+<text text-anchor="middle" x="1438" y="-373.8" font-family="arial" font-size="14.00">MeetSemilattice</text>
 </g>
 <!-- Lattice&#45;&gt;MeetSemilattice -->
-<g id="edge44" class="edge"><title>Lattice-&gt;MeetSemilattice</title>
-<path fill="none" stroke="black" d="M1098.21,-318.189C1104.36,-320.306 1110.85,-322.366 1117,-324 1189.5,-343.26 1273.94,-357.714 1333.5,-366.622"></path>
-<polygon fill="black" stroke="black" points="1333.18,-370.112 1343.58,-368.113 1334.2,-363.188 1333.18,-370.112"></polygon>
+<g id="edge52" class="edge"><title>Lattice-&gt;MeetSemilattice</title>
+<path fill="none" stroke="black" d="M1126.21,-318.189C1132.36,-320.306 1138.85,-322.366 1145,-324 1217.5,-343.26 1301.94,-357.714 1361.5,-366.622"></path>
+<polygon fill="black" stroke="black" points="1361.18,-370.112 1371.58,-368.113 1362.2,-363.188 1361.18,-370.112"></polygon>
 </g>
 <!-- BoundedMeetSemilattice&#45;&gt;MeetSemilattice -->
-<g id="edge49" class="edge"><title>BoundedMeetSemilattice-&gt;MeetSemilattice</title>
-<path fill="none" stroke="black" d="M1472.15,-323.945C1461.6,-332.953 1448.47,-344.158 1437.01,-353.947"></path>
-<polygon fill="black" stroke="black" points="1434.72,-351.298 1429.38,-360.453 1439.26,-356.622 1434.72,-351.298"></polygon>
+<g id="edge57" class="edge"><title>BoundedMeetSemilattice-&gt;MeetSemilattice</title>
+<path fill="none" stroke="black" d="M1500.15,-323.945C1489.6,-332.953 1476.47,-344.158 1465.01,-353.947"></path>
+<polygon fill="black" stroke="black" points="1462.72,-351.298 1457.38,-360.453 1467.26,-356.622 1462.72,-351.298"></polygon>
 </g>
 </g>
 </svg>


Test patch:
diff --git a/test/Either.ts b/test/Either.ts
index 5608c87e..25112b23 100644
--- a/test/Either.ts
+++ b/test/Either.ts
@@ -16,14 +16,18 @@ import {
   fromRefinement,
   getCompactable,
   getFilterable,
-  getWitherable
+  getWitherable,
+  getApplySemigroup,
+  getApplyMonoid,
+  getSemigroup
 } from '../src/Either'
 import { none, option, some } from '../src/Option'
 import { setoidNumber, setoidString } from '../src/Setoid'
 import { traverse } from '../src/Traversable'
 import { failure, success } from '../src/Validation'
-import { monoidString } from '../src/Monoid'
+import { monoidString, monoidSum } from '../src/Monoid'
 import { Identity, identity as I } from '../src/Identity'
+import { semigroupSum } from '../src/Semigroup'
 
 describe('Either', () => {
   it('fold', () => {
@@ -360,4 +364,28 @@ describe('Either', () => {
       )
     })
   })
+
+  it('getSemigroup', () => {
+    const S = getSemigroup<string, number>(semigroupSum)
+    assert.deepEqual(S.concat(left('a'), left('b')), left('a'))
+    assert.deepEqual(S.concat(left('a'), right(2)), right(2))
+    assert.deepEqual(S.concat(right(1), left('b')), right(1))
+    assert.deepEqual(S.concat(right(1), right(2)), right(3))
+  })
+
+  it('getApplySemigroup', () => {
+    const S = getApplySemigroup<string, number>(semigroupSum)
+    assert.deepEqual(S.concat(left('a'), left('b')), left('a'))
+    assert.deepEqual(S.concat(left('a'), right(2)), left('a'))
+    assert.deepEqual(S.concat(right(1), left('b')), left('b'))
+    assert.deepEqual(S.concat(right(1), right(2)), right(3))
+  })
+
+  it('getApplyMonoid', () => {
+    const S = getApplyMonoid<string, number>(monoidSum)
+    assert.deepEqual(S.concat(left('a'), S.empty), left('a'))
+    assert.deepEqual(S.concat(S.empty, left('b')), left('b'))
+    assert.deepEqual(S.concat(right(1), S.empty), right(1))
+    assert.deepEqual(S.concat(S.empty, right(2)), right(2))
+  })
 })
diff --git a/test/Foldable.ts b/test/Foldable.ts
index e184a7f4..2b2edd90 100644
--- a/test/Foldable.ts
+++ b/test/Foldable.ts
@@ -17,7 +17,8 @@ import {
   sequence_,
   sum,
   toArray,
-  traverse_
+  traverse_,
+  traverse
 } from '../src/Foldable'
 import { IO, io } from '../src/IO'
 import { monoidString } from '../src/Monoid'
@@ -115,4 +116,11 @@ describe('Foldable', () => {
   it('foldr', () => {
     assert.deepEqual(foldr(array)(['a', 'b', 'c'], '', (a, acc) => acc + a), 'cba')
   })
+
+  it('traverse', () => {
+    let counter = ''
+    const x = traverse(io, array)(['a', 'b', 'c'], a => new IO(() => (counter += a)))
+    x.run()
+    assert.strictEqual(counter, 'abc')
+  })
 })
diff --git a/test/NonEmptyArray.ts b/test/NonEmptyArray.ts
index 191ce980..15f8e60a 100644
--- a/test/NonEmptyArray.ts
+++ b/test/NonEmptyArray.ts
@@ -1,6 +1,6 @@
 import * as assert from 'assert'
 import { fold, monoidSum } from '../src/Monoid'
-import { NonEmptyArray, nonEmptyArray, fromArray, getSemigroup } from '../src/NonEmptyArray'
+import { NonEmptyArray, nonEmptyArray, fromArray, getSemigroup, group, groupSort } from '../src/NonEmptyArray'
 import { none, option, some } from '../src/Option'
 import { ordNumber } from '../src/Ord'
 import { traverse } from '../src/Traversable'
@@ -94,6 +94,25 @@ describe('NonEmptyArray', () => {
     assert.deepEqual(S.concat(new NonEmptyArray(1, [2]), new NonEmptyArray(3, [4])), new NonEmptyArray(1, [2, 3, 4]))
   })
 
+  it('group', () => {
+    assert.deepEqual(group(ordNumber)([1, 2, 1, 1]), [
+      new NonEmptyArray(1, []),
+      new NonEmptyArray(2, []),
+      new NonEmptyArray(1, [1])
+    ])
+
+    assert.deepEqual(group(ordNumber)([1, 2, 1, 1, 3]), [
+      new NonEmptyArray(1, []),
+      new NonEmptyArray(2, []),
+      new NonEmptyArray(1, [1]),
+      new NonEmptyArray(3, [])
+    ])
+  })
+
+  it('groupSort', () => {
+    assert.deepEqual(groupSort(ordNumber)([1, 2, 1, 1]), [new NonEmptyArray(1, [1, 1]), new NonEmptyArray(2, [])])
+  })
+
   it('last', () => {
     assert.deepEqual(new NonEmptyArray(1, [2, 3]).last(), 3)
     assert.deepEqual(new NonEmptyArray(1, []).last(), 1)
diff --git a/test/Option.ts b/test/Option.ts
index 6c2b34fe..f721f81b 100644
--- a/test/Option.ts
+++ b/test/Option.ts
@@ -18,14 +18,17 @@ import {
   option,
   some,
   tryCatch,
-  getRefinement
+  getRefinement,
+  getApplySemigroup,
+  getApplyMonoid
 } from '../src/Option'
 import { ordString } from '../src/Ord'
-import { semigroupString } from '../src/Semigroup'
+import { semigroupString, semigroupSum } from '../src/Semigroup'
 import { setoidNumber } from '../src/Setoid'
 import { traverse } from '../src/Traversable'
 import { identity } from '../src/function'
 import { Identity, identity as I } from '../src/Identity'
+import { monoidSum } from '../src/Monoid'
 
 const p = (n: number): boolean => n > 2
 
@@ -200,20 +203,36 @@ describe('Option', () => {
     assert.strictEqual(some(3).reduce(2, (b, a) => b + a), 5)
   })
 
+  it('getApplySemigroup', () => {
+    const S = getApplySemigroup(semigroupSum)
+    assert.deepEqual(S.concat(none, none), none)
+    assert.deepEqual(S.concat(some(1), none), none)
+    assert.deepEqual(S.concat(none, some(1)), none)
+    assert.deepEqual(S.concat(some(1), some(2)), some(3))
+  })
+
+  it('getApplyMonoid', () => {
+    const M = getApplyMonoid(monoidSum)
+    assert.deepEqual(M.concat(M.empty, none), none)
+    assert.deepEqual(M.concat(none, M.empty), none)
+    assert.deepEqual(M.concat(M.empty, some(1)), some(1))
+    assert.deepEqual(M.concat(some(1), M.empty), some(1))
+  })
+
   it('getFirstMonoid', () => {
-    const first = getFirstMonoid<number>()
-    assert.deepEqual(first.concat(none, some(1)), some(1))
-    assert.deepEqual(first.concat(some(1), none), some(1))
-    assert.deepEqual(first.concat(none, none), none)
-    assert.deepEqual(first.concat(some(1), some(2)), some(1))
+    const M = getFirstMonoid<number>()
+    assert.deepEqual(M.concat(none, none), none)
+    assert.deepEqual(M.concat(some(1), none), some(1))
+    assert.deepEqual(M.concat(none, some(1)), some(1))
+    assert.deepEqual(M.concat(some(1), some(2)), some(1))
   })
 
   it('getLastMonoid', () => {
-    const last = getLastMonoid<number>()
-    assert.deepEqual(last.concat(none, some(1)), some(1))
-    assert.deepEqual(last.concat(some(1), none), some(1))
-    assert.deepEqual(last.concat(none, none), none)
-    assert.deepEqual(last.concat(some(1), some(2)), some(2))
+    const M = getLastMonoid<number>()
+    assert.deepEqual(M.concat(none, none), none)
+    assert.deepEqual(M.concat(some(1), none), some(1))
+    assert.deepEqual(M.concat(none, some(1)), some(1))
+    assert.deepEqual(M.concat(some(1), some(2)), some(2))
   })
 
   it('contains', () => {
diff --git a/test/StrMap.ts b/test/StrMap.ts
index 4eb3f6a6..79ead4ca 100644
--- a/test/StrMap.ts
+++ b/test/StrMap.ts
@@ -84,7 +84,8 @@ describe('StrMap', () => {
   })
 
   it('toArray', () => {
-    assert.deepEqual(toArray(new StrMap({ a: 1 })), [['a', 1]])
+    assert.deepEqual(toArray(new StrMap({ a: 1, b: 2 })), [['a', 1], ['b', 2]])
+    assert.deepEqual(toArray(new StrMap({ b: 2, a: 1 })), [['a', 1], ['b', 2]])
   })
 
   it('toUnfoldable', () => {
diff --git a/test/Task.ts b/test/Task.ts
index e5af4e43..1eaf28b5 100644
--- a/test/Task.ts
+++ b/test/Task.ts
@@ -2,15 +2,7 @@ import * as assert from 'assert'
 import { left, right } from '../src/Either'
 import { IO } from '../src/IO'
 import { monoidString } from '../src/Monoid'
-import { Task, fromIO, getMonoid, getRaceMonoid, task, tryCatch } from '../src/Task'
-
-const delay = <A>(n: number, a: A): Task<A> =>
-  new Task<A>(
-    () =>
-      new Promise<A>(resolve => {
-        setTimeout(() => resolve(a), n)
-      })
-  )
+import { Task, fromIO, getMonoid, getRaceMonoid, task, tryCatch, delay } from '../src/Task'
 
 const delayReject = <A>(n: number, a: A): Task<A> =>
   new Task<A>(