# fp-in-kotlin


09/10/2021, 2:04 PM
Hi guys, I want to ask some questions, my English is poor, but I will attach a code example. Thank you for reading this message. I try code of FP style in kotlin. I use SUM type (
sealed class
) and pattern matching (
) to enable functions to match different types to complete different tasks. This makes most of my functions need to do a pattern matching on the type, which makes me feel a little clumsy, and if I need to add a new type, I need to add a case to each of these functions, it is easy to miss the new case. The following is a fictitious code example, assuming it is a sticky note model.
Copy code
sealed class Resource {
    data class Note(val content: String?) : Resource()
    data class Tag(val name: String?) : Resource()
    data class Character(val name: String?) : Resource()
    data class Address(val latitude: Float?, val longitude: Float?) : Resource()

fun pullResource(): List<Resource> = TODO()

fun Resource.toDecrypt(): Resource = when (this) {
    is Resource.Note -> TODO()
    is Resource.Tag -> TODO()
    is Resource.Character -> TODO()
    is Resource.Address -> TODO()

fun Resource.checkLegal(): Boolean = when (this) {
    is Resource.Note -> content != null
    is Resource.Tag -> name != null
    is Resource.Character -> name != null
    is Resource.Address -> latitude != null && longitude != null

inline fun <reified T> List<T>.insert() {
    when (T::class) {
        Resource.Note::class -> TODO("batch insert into the Note Entity")
        Resource.Tag::class -> TODO("batch insert into the Tag Entity")
        Resource.Character::class -> TODO("batch insert into the Character Entity")
        Resource.Address::class -> TODO("batch insert into the Address Entity")

fun insertDB(l: List<Resource>) {
    fun <T : Resource> List<Resource>.cast(): List<T> = this as List<T>

    l.groupBy {
        when (it) {
            is Resource.Note -> "Note"
            is Resource.Tag -> "Tag"
            is Resource.Character -> "Character"
            is Resource.Address -> "Address"
    }.let {

fun main() {
I don’t know if this is right, it feel weird to me. If in OO style, I thought maybe i can define an interface for Resource, and implement the interface when adding cases. The code is clean and does not miss new cases.


10/02/2021, 7:57 PM
Hi, @Giovan. Sorry for the late response. I hope you haven't given up on FP 😅! Yes, this sort of pattern is very common in Kotlin FP. I felt the same weirdness/resistance to it when I first started FP. It's normal. I can think of one way to make functions like
and its friends more generic. I hope the following will give you some ideas about further experiments you can try.
Copy code
sealed interface Resource

interface InsertOp<T : Resource> {
   fun insert(resources: List<T>): Resource

interface DecryptOp<T : Resource> {
    fun decrypt(resource: Resource): Resource

interface ResourceOps<T : Resource> : InsertOp<T>, DecryptOp<T>

fun <T : Resource> List<T>.insert(insertable: InsertOp<T>): List<Resource> {
    return this

fun <T : Resource> Resource.decrypt(decryptOp: DecryptOp<T>): Resource =

fun <T : Resource> ops(resource: T): ResourceOps<T> = TODO()

fun pullResource(): List<Resource> = TODO()

fun go() {
        .map { Pair(it, ops(it)) }
        .map { Pair(it.second.decrypt(it.first), it.second) }
        .groupBy { it.second }
        .forEach { entry ->
            entry.key.insert( { it.first })
There's boilerplate in
that could probably be eliminated with additional abstraction and refactoring.
You said it's easy to miss a case. But actually, it's not, because the compiler requires that your
expressions handle all cases. And as of Kotlin
you can also opt in to require exhaustive