ListK

beginner

ListK wraps over the platform List type to make it a type constructor.

It can be created from Kotlin List type with a convenient k() function.

import arrow.*
import arrow.data.*

listOf(1, 2, 3).k()
// ListK(list=[1, 2, 3])

For most use cases you will never use ListK directly but List directly with the extension functions that Arrow projects over it.

ListK implements operators from many useful typeclasses.

The @extension type class processor expands all type class combinators that ListK provides automatically over List

For instance, it has combineK from the SemigroupK typeclass.

It can be used to cheaply combine two lists:

import arrow.instances.list.semigroupK.*

val hello = listOf('h', 'e', 'l', 'l', 'o')
val commaSpace = listOf(',', ' ')
val world = listOf('w', 'o', 'r', 'l', 'd')

hello.combineK(commaSpace).combineK(world)
// ListK(list=[h, e, l, l, o, ,,  , w, o, r, l, d])

The functions traverse and sequence come from Traverse.

Traversing a list creates a new container Kind<F, A> by combining the result of a function applied to each element:

import arrow.core.*
import arrow.instances.*
import arrow.instances.option.applicative.*
import arrow.instances.list.traverse.*

val numbers = listOf(Math.random(), Math.random(), Math.random())
numbers.traverse(Option.applicative(), { if (it > 0.5) Some(it) else None })
// Some(ListK(list=[0.5121343622972414, 0.549311117080666, 0.5397216943111476]))

and complements the convenient function sequence() that converts a list of ListK<Kind<F, A>> into a Kind<F, ListK<A>>:

fun andAnother() = Some(Math.random())

val requests = listOf(Some(Math.random()), andAnother(), andAnother())
requests.sequence(Option.applicative())
// Some(ListK(list=[0.005511980620282908, 0.6051796093105604, 0.14121609259659718]))

If you want to aggregate the elements of a list into any other value you can use foldLeft and foldRight from Foldable.

Folding a list into a new value, String in this case, starting with an initial value and a combine function:

listOf('a', 'b', 'c', 'd', 'e').k().foldLeft("-> ") { x, y -> x + y }
// -> abcde

Or you can apply a list of transformations using ap from Applicative.

import arrow.instances.*
import arrow.instances.list.applicative.*

listOf(1, 2, 3).ap(listOf({ x: Int -> x + 10}, { x: Int -> x * 2}))
// ListK(list=[11, 12, 13, 2, 4, 6])

Supported type classes

Module Type classes
arrow.aql Count, From, GroupBy, OrderBy, Select, Sum, Union, Where
arrow.mtl.typeclasses FunctorFilter, MonadCombine, MonadFilter
arrow.optics.typeclasses Cons, Each, FilterIndex, Index, Snoc
arrow.typeclasses Applicative, Eq, Foldable, Functor, Hash, Monad, Monoid, MonoidK, Semigroup, SemigroupK, Show, Traverse