rcd27
08/06/2019, 9:37 AMMapK.traverse(..)
method. Any code of how to use it?Imran/Malic
08/06/2019, 12:03 PMrcd27
08/06/2019, 12:05 PMMapK
, figuring out what each method is used for. And I just can't hello-world this `traverse`:
val map1: MapK<String, Int> = mapOf("one" to 1, "two" to 2).k()
map1.traverse<String, Int>(
object : Applicative<String> {
override fun <A> just(a: A): Kind<String, A> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun <A, B> Kind<String, A>.ap(ff: Kind<String, (A) -> B>): Kind<String, B> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
},
{ f ->
})
Imran/Malic
08/06/2019, 12:09 PMrcd27
08/06/2019, 12:10 PMImran/Malic
08/06/2019, 12:15 PM(A) -> Kind<G, B>
.
Well what does that mean, whenever you want to introduce a new Shape let’s say you want to go from List<String>
to Validated<Nil<NumberFormatException, List<Int>>
This would facilitate to safely parse Strings to Int, while accumulating Errors on the way.Imran/Malic
08/06/2019, 12:15 PMimport arrow.core.Either
import arrow.core.Nel
import arrow.core.ValidatedNel
import arrow.core.extensions.nonemptylist.semigroup.semigroup
import arrow.core.extensions.validated.applicative.applicative
import arrow.core.fix
import arrow.core.invalidNel
import arrow.core.k
import arrow.core.validNel
fun parseIntEither(s: String): Either<NumberFormatException, Int> =
if (s.matches(Regex("-?[0-9]+"))) Either.Right(s.toInt())
else Either.Left(NumberFormatException("$s is not a valid integer."))
fun parseIntValidated(s: String): ValidatedNel<NumberFormatException, Int> =
if (s.matches(Regex("-?[0-9]+"))) s.toInt().validNel()
else NumberFormatException("$s is not a valid integer.").invalidNel()
fun main() {
//sampleStart
val validatedList = listOf("1", "22w", "3", "33s").k()
.traverse(ValidatedNel.applicative(Nel.semigroup<NumberFormatException>()), ::parseIntValidated).fix()
//sampleEnd
println(validatedList)
}
Imran/Malic
08/06/2019, 12:16 PMIO
Imran/Malic
08/06/2019, 12:22 PMG
has to something else than String, because String is not a container. B
on the other hand is the output value from A
which in your case is Int
. In the case of MapK you would traverse over the Values A
rcd27
08/06/2019, 12:27 PMImran/Malic
08/06/2019, 12:28 PM::identity
it would collapse what ever is in that F
and turns an F<G<A>>
to a `G<F<A>>`:
Here is an example with a List<Option<Int>>
, which yields a `Option<List<Int>>`:
import arrow.core.extensions.option.applicative.applicative
import arrow.core.extensions.option.applicative.map
import arrow.core.fix
import arrow.core.identity
import arrow.core.none
import arrow.core.some
import arrow.core.Option
fun main() {
//sampleStart
val optionList: Option<List<Int>> =
listOf(1.some(), 2.some(), 3.some())
.traverse(Option.applicative(), ::identity).fix().map { it.fix() }
val emptyList: Option<List<Int>> =
listOf(1.some(), none(), 3.some())
.traverse(Option.applicative(), ::identity).map { it.fix() }
//sampleEnd
println("optionList = $optionList")
println("emptyList = $emptyList")
}
And this is what sequence do out of the box.
import arrow.core.Option
import arrow.core.extensions.list.traverse.sequence
import arrow.core.extensions.option.applicative.applicative
import arrow.core.none
import arrow.core.some
fun main() {
//sampleStart
val optionList =
listOf(1.some(), 2.some(), 3.some())
.sequence(Option.applicative())
val emptyList =
listOf(1.some(), none(), 3.some())
.sequence(Option.applicative())
//sampleEnd
println("optionList = $optionList")
println("emptyList = $emptyList")
}
rcd27
08/06/2019, 12:29 PMOption.applicative()
for the list example...Imran/Malic
08/06/2019, 12:29 PMImran/Malic
08/06/2019, 12:29 PMrcd27
08/06/2019, 12:31 PMImran/Malic
08/06/2019, 12:31 PMImran/Malic
08/06/2019, 12:32 PMImran/Malic
08/06/2019, 12:32 PM0.10.0-Snapshot
rcd27
08/06/2019, 12:33 PMrcd27
08/06/2019, 12:34 PMrcd27
08/06/2019, 12:35 PMImran/Malic
08/06/2019, 12:36 PMrcd27
08/06/2019, 12:37 PMImran/Malic
08/06/2019, 12:38 PMF
and wrap with in a new container G
Imran/Malic
08/06/2019, 12:42 PMMapK
within the boundaries of another container G
. Well obviously you could use fold, but fold has another purpose. It aims to give you that B
and doesn’t care from which existing container e.g.: MapK
it is called.Imran/Malic
08/06/2019, 12:43 PM(A<B<C>>) -> B<A<C>>
and here you would use sequence
Imran/Malic
08/06/2019, 12:49 PMrcd27
08/06/2019, 12:50 PMImran/Malic
08/06/2019, 1:01 PMval d = map1.traverse(Option.applicative()) { Some("$it") }
val dBoiler = map1.foldLeft(Some(emptyMap())) { acc: Option<MapK<String, String>>, i: Int -> acc.fold({emptyMap()}, { /*Some logic to retrieve the key of a value and transform it*/ } )}
Generally both try to do the same thing, but I let you judge what makes more sense