Hi all, FP newbie here trying to do a deep dive in...
# arrow
i
Hi all, FP newbie here trying to do a deep dive into
Arrow
and playing today with
Validated
. As a learning exercise to explain myself and others if Validated is an
Applicative
I am checking wether it satisfies Functor and Applicative laws. I am doing that verification using
Kotest
using a specific instance of
Validated<Nothing, String?>
- so really only formally checking those laws against that specific Type. I got stuck at verifying
Interchange
and
Composition
law for
Applicative
and finally came up with this try for both:
Copy code
"Validated applicative must satisfy interchange law" {
        checkAll(genNullableString) { a ->
            val f = { b: String? -> "PRE-APPENDED${b}" }
            val validatedF1 = Validated.lift<Nothing, String?, String?>(f)
            val validatedF2 = Validated.lift<Nothing, (String?) -> String?, String?> { f -> f(a) }
            validatedF1(a.valid()) shouldBe validatedF2(f.valid())
        }
    }
"Validated applicative must satisfy composition law" {
        checkAll(genNullableString) { a ->
            val f = { b: String? -> "PRE-APPENDED${b}" }
            val g = { b: String? -> "${b}POST-APPENDED" }
            val validatedF1 = Validated.lift<Nothing, String?, String?>(f)
            val validatedF2 = Validated.lift<Nothing, String?, String?>(g)
            (validatedF2.compose(validatedF1))(a.valid()) shouldBe validatedF1(validatedF2(a.valid()))
        }
    }
I am not sure if I have been able to replicated in
Kotlin
and
Kotest
what in Haskell would have been: •
u <*> pure y *=* pure ($ y) <*> u
for Interchange law and, •
pure (.) <*> u <*> v <*> w *=* u <*> (v <*> w)
for Composition law Are the above Kotest tests really checking what Interchange and Composition laws are for Applicatives? Or I am completely lost? Thank you very much for bringing
Arrow
to us.
r
Hi @Ivan Lorenz, and welcome! At first sight your implementation looks right but there is a fundamental difference on how the applicative laws would be encoded in Kotlin. While in Haskell function lifting and
ap
is a natural way to express those laws in Kotlin it would be easier to express the applicative laws in terms of map2, which we call zip. zip shows the composition of two independent operations. In terms of zip or map2 they may look like:
Copy code
Left identity: zip(unit(()), fa)((_,a) => a) == fa
Right identity: zip(fa, unit(()))((a,_) => a) == fa
Associativity: product(product(fa, fb),fc) == map(product(fa, product(fb, fc)))(assoc)
Naturality: zip(a,b)(productF(f,g)) == product(map(a)(f), map(b)(g))
I looked these up because I don’t remember these off my head so don’t take it literally please. Arrow also has a special superpower for Validated which beside letting it provide the behavior of an Applicative Functor it also can bring it up to Monadic land making it equivalent to Either. For example in Arrow you can in place monad bind with the continuation system validation values like this:
Copy code
either {
  val a = validatedValue.bind()
  a + b
} // exists with Either
Unlike in Scala or Haskell these blocks work with effect and suspend function and can’t intermix effects without the need of monad transformers or stacks of effects. They all cooperate through the continuation together that is in the scope of the block,
I digged back in the vault of old arrow and here is how we had implemented the Applicative laws back then https://github.com/arrow-kt/arrow-core/blob/40619f87b7/arrow-core-test/src/main/kotlin/arrow/core/test/laws/ApplicativeLaws.kt
We had plans to bring some back if there is support for kinds in the future through compiler plugins, in whatever case if you have new behaviours that want to add to the arrow test suite as you explore please consider sending a PR to enhance the coverage of Validated 🙏 .
i
Awesome answer and level of detail @raulraja. I will explore verifying those laws in terms of
zip
also while keeping those tests I wrote using
lift
. If I am able to bring something new to the table about the coverage for
Validated
I will send a PR, but honestly my knowledge about
Arrow
and FP is far away from the point of contribution. Just learning from you guys and passionate about using some parts of FP with Arrow into my daily OOP code until the time I can do a total paradigm switch. Thank you very much.
r
thank you Ivan! looking forward to seeing you around here and feel free to bring any questions 🙂