https://kotlinlang.org logo
#functional
Title
# functional
r

reactormonk

09/02/2022, 1:22 PM
I've got
Copy code
kotlin
@JsonClass(generateAdapter = true)
data class Gallery<T>(val galleryItems: List<GalleryItem<T>>)

@JsonClass(generateAdapter = true, generator = "sealed:type")
sealed interface GalleryItem<T> {
    @TypeLabel("photo")
    @JsonClass(generateAdapter = true)
    data class Photo<T>(val url: T): GalleryItem<T>
    @TypeLabel("video")
    @JsonClass(generateAdapter = true)
    data class Video<T>(val url: T): GalleryItem<T>
}
And
Copy code
val x: Gallery<String>
as well as
Copy code
fun parse(x: String): HttpUrl
and I would like a
Gallery<HttpUrl>
in the end. In Haskell, I'd add a
deriving Functor
to the type declaration and then I could use all the fun combinatorics functions. How would I do that in Kotlin?
s

simon.vergauwen

09/02/2022, 1:25 PM
deriving Functor
😅 There is nothing like that sadly. Your best is to write a bit of boilerplate IMO.
Copy code
fun <A, B> Gallery<A>.map(transform: (A) -> B)" Gallery<B> = map {
  when(this) {
    is Photo -> Photo(transform(url))
    is Video -> Video(transform(url))
  }
}
That of course doesn't give you all the other goodies from
Functor
& co
r

reactormonk

09/02/2022, 1:26 PM
Apparently I can't have a type-changing
copy
either 😞
s

simon.vergauwen

09/02/2022, 1:27 PM
I'm not sure if you've ever looked into #arrow, but it's a functional library / organisation like many you can find in Scala or other languages. We've been experimenting with things like this for a long time, but we've seen that since Kotlin doesn't support higher kinded types so doing things like ad-hoc polymorphism with typeclasses is not very ergonomic or idiomatic in Kotlin
Aha, but there is a pretty good Optics library !
r

reactormonk

09/02/2022, 1:27 PM
Now we're talking
s

simon.vergauwen

09/02/2022, 1:27 PM
It can generate Optics for data classes and sealed classes out the box for multiplatform projects 🙂
r

reactormonk

09/02/2022, 1:28 PM
Can I make type-changing lenses? 🤔
s

simon.vergauwen

09/02/2022, 1:29 PM
Yes! It supports polymorhic optics, but those cannot be generated out-of-the-box IIRC
Or rather, I'm not sure if the generator support it at the time.
r

reactormonk

09/02/2022, 1:30 PM
Lemme see
Moshi doesn't like my generic sealed classes anyway
Rowtypes when? 😄
If you've never worked with them, PureScript has a really cool implementation. They're a godsend working with JSON of any form or sort.
s

simon.vergauwen

09/02/2022, 1:38 PM
I've only toyed with them, but since almost all my work has been constraint to Kotlin for quite some time I've been trying to improve the status quo here 😄 I've used this as well when working with cumbersome Json, https://github.com/nomisRev/kotlinx-serialization-jsonpath
r

reactormonk

09/02/2022, 1:39 PM
Neato!
Not too much json work here so far, so all fine.
s

simon.vergauwen

09/02/2022, 1:40 PM
I've been mostly interested on leveraging the Kotlin Coroutine system as an effect system, and being able to reason about effects in a principled way. So you're able to leverage structured concurrency to reason about resource safety for example. https://github.com/arrow-kt/suspendapp#suspendapp-arrows-resource
So trying to flatten all monads, and patterns into
suspend
without losing any guarantees or patterns we are used to from working with
IO
or other monads. This has also eliminated the need for monad transformers, which is quite significant on the JVM which doesn't like a lot of nesting, or capturing lambdas.
r

reactormonk

09/02/2022, 1:49 PM
Reminds me roughly of https://www.fpcomplete.com/blog/2018/10/resourcet-necessary-evil/ but I have no clue if it applies or not, never dug too much into correctness of effect systems
s

simon.vergauwen

09/02/2022, 1:53 PM
It's kind of a necessary evil yes 😅 Most "complex" systems will interact with other services (resources), and that typically requires connection pools to be efficient. So you're most of the time dealing with some of these concerns. To avoid overuse we typically isolate that usage to where dependency graphs are setup, and with
suspend
we also aim to eliminate the return types in the wrappers. Similar to effect systems so you can do things like.
Copy code
suspend fun ResourceScope.myResource(): A =
  autoCloseable { ConstructResource() }
Some design documents on this for Arrow 2.0: Resource Polymorphic effects
66 Views