DEV Community

Discussion on: Know When to Fold 'Em

Collapse
 
jbristow profile image
Jon Bristow • Edited

ok, I did the arrow-kt, and at this point it feels like I should just use Haskell.

import arrow.Kind
import arrow.core.Eval
import arrow.core.Option
import arrow.core.none
import arrow.core.some
import arrow.data.ListK
import arrow.data.k
import arrow.instances.listk.foldable.foldable
import arrow.instances.listk.monoid.monoid
import arrow.instances.monoid
import arrow.instances.option.foldable.foldable
import arrow.instances.option.monoid.monoid
import arrow.instances.semigroup
import arrow.typeclasses.Foldable
import arrow.typeclasses.Monoid

fun <F, A> myElem(foldableKind: Kind<F, A>, FO: Foldable<F>, elem: A) = FO.run {
    foldableKind.foldRight(Eval.False) { a, eval -> eval.map { it || (a == elem) } }.value()
}

fun <FA, A, B> myMap(k: Kind<FA, A>, FO: Foldable<FA>, MO: Monoid<B>, fn: (A) -> B): B {
    return FO.run {
        k.foldRight(Eval.now(MO.empty())) { a: A, eval: Eval<B> ->
            eval.map { MO.run { it + fn(a) } }
        }.value()
    }
}

fun main(args: Array<String>) {

    val a = myElem(none(), Option.foldable(), 123)
    // a:false
    println("a:$a")

    val b = myElem(123.some(), Option.foldable(), 123)
    // b:true
    println("b:$b")

    val c = myElem(listOf(1, 2, 123, 3).k(), ListK.foldable(), 123)
    // c:true
    println("c:$c")

    val d = myMap(listOf(1, 2, 3, 4).k(), ListK.foldable(), ListK.monoid()) { listOf("str:$it").k() }.list
    // d:[str:4, str:3, str:2, str:1]
    println("d:$d")

    val e = myMap(listOf(1, 2, 3, 4).k(), ListK.foldable(), Int.monoid(), 2::times)
    // e:20
    println("e:$e")

    val f = myMap(listOf(1, 2, 3, 4).k(), ListK.foldable(), Option.monoid(Int.semigroup())) {
        if (it > 2) (it + 5).some() else none()
    }
    // f:Some(17)
    println("f:$f")
}

I feel like I'm missing some idioms here on how to use arrow-kt properly. What we have here is myElem implemented so that any type that has a matching Foldable TypeClass can use this function. Maybe I need less toy examples?

I really don't like having to pass in utility objects just to tell it what kind of Monoid/Foldable I am. It's really showing off how strong Haskell's type system is.