Ivan Lorenz
11/18/2021, 1:52 PMArrow
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:
"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.raulraja
11/18/2021, 2:46 PMap
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:
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:
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,raulraja
11/18/2021, 2:54 PMraulraja
11/18/2021, 2:55 PMIvan Lorenz
11/18/2021, 7:25 PMzip
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.raulraja
11/18/2021, 7:48 PM