https://kotlinlang.org logo
Join SlackCommunities
Powered by
# fp-in-kotlin
  • j

    julian

    10/12/2020, 6:02 PM
    set the channel description: Discussion of the book Functional Programming in Kotlin by Marco Vermeulen
  • j

    julian

    10/12/2020, 6:03 PM
    set the channel description: Discussion of the book "Functional Programming in Kotlin" by Marco Vermeulen
  • j

    julian

    10/12/2020, 6:07 PM
    The book can be found on Manning's website at https://www.manning.com/books/functional-programming-in-kotlin.
  • j

    julian

    10/12/2020, 7:57 PM
    Welcome! šŸ˜„ I started this channel because I'm working my way through all the exercises in the book "FP in Kotlin" and I wished I had a place to chat about FP in the context of the book, and offer and receive advice and encouragement.
    šŸ‘ 3
  • k

    Kirill

    10/14/2020, 7:40 PM
    šŸ‘€
    j
    • 2
    • 1
  • j

    julian

    10/26/2020, 5:44 PM
    Hi, all! šŸ˜„ I'm curious to know how others are doing working through the book. For example: What chapter are you on? What's easy, what's hard? Are you doing the exercises? How's that going? Are you able to apply what you're learning to real life problems? And anything else you'd like to share...
  • t

    tim

    11/06/2020, 6:53 PM
    Just bought the book so chapter 1! Not sure if I'll do the exercises (would love to time permitting) but definitely planning on applying the lessons to our codebase which strives to be FP but I'm sure there is plenty of room for improvement!
    j
    • 2
    • 2
  • j

    julian

    11/08/2020, 7:20 PM
    Since I asked the questions, I should answer them too! šŸ˜„ I've found this book much better to follow than the Red Book. I think primarily because that one was in Scala, which I had no experience with. But also because since then I've absorbed quite a bit about FP through other sources like #arrow, blog posts, etc. There's something that I've noticed with FP - at least for me - after reading or learning something new, it takes a while for the meaning and implications to start to deepen. Amazingly this appears to happen without any direct additional effort on my part, other than just continuing to maintain FP as an object of interest. I also dive into the Arrow source code sometimes, especially for the parts that seem to come up a lot in readings or usage - data types like Either, and typeclasses like Functor, Applicative, and Monad, for instance. For the first year or so of FP I was quite intimidated by its seeming complexity and foreignness, and I avoided reading the source because I figured it would be too overwhelming. Maybe my head would explode or something. And it was overwhelming, actually. But returning to it repeatedly has yielded slow but steady improvement in my understanding. I'm on chapter 8, which has been the most challenging so far, followed by chapter 7. These chapters deal, not with the nuts-and-bolts of FP, but with functional design. Giving myself permission to go as slowly as I need to to reach full understanding seems to be a good approach for me. I've also found that refactoring code that I have trouble understanding, into a form that makes sense to me, (while remaining true to the correctness of the original code, of course) has been helpful. It allows me to keep moving forward even when I'm "stuck" on a chapter. I am trying to do all the exercises. But I sometimes skip ones that are either too easy, or too hard but that I want to return to later after the subconscious learning processes I mentioned earlier have had an opportunity to do their work. I am applying it, as much as I can reasonably, to an Android project that I'm the sole developer on. But I have to be cautious about not getting in too over my head. And I have to keep in mind that, the deeper I go, the more likely Android devs coming to the project could find it all as foreign and intimidating as I used to. But the release of arrow-fx-coroutines Streams means that an FP Android project actually now looks a whole lot like one using a reactive streams architecture with Rx. That's a big win, I think, for FP gaining wider usage in the Android community.
    p
    • 2
    • 2
  • p

    pajatopmr

    03/28/2021, 5:51 AM
    tldr; I bought the book about a year ago which was probably the fourth year of my Kotlin awareness and third year of using it daily in my job as an Android app developer. Skimmed it but did not embrace it for deep learning until a few weeks ago. Now I am forcing myself to deep dive into FP using the book and have most of my development work on hold for a while. My company, my choice. šŸ™‚ It might be interesting to the three of you who got this far to hear my FP story. I first heard of FP in the late 80's at a conference at MIT. I was working with Richard Stallman at the time on Emacs (elisp) but mostly using C. My day job was building high performance computers for a minicomputer company (Data General) writing microcode. It was clear to me that FP was not even close to being ready for prime time use by mainstream software developers. Over the subsequent years though, I kept seeing FP inching forward like a huge freight train heading towards the station but never quite pulling in. I always recognized the inherent value of immutable data and higher order functions but not so much pure functions or algebraic data types. About six or so years ago, as I was starting Android work for Brightcove, when a half dozen or so engineers decided to do a weekly Haskell lunchtime learning session using the O'Reilly book. Six weeks or so into that effort, I suggested we do a Haskell project of some significance. The two, maybe three, FP/Haskell gurus responded that that was not going to happen as FP and Haskell were merely for intellectual study and still not ready for prime time. My part of that effort ended there. Then a few years ago I saw that Uncle Bob had bought into FP (using Clojure) which convinced me that the FP train had landed. Arrow's popularity in the Kotlin world did not go unnoticed either. I am now into parts of Chapters 3, 4, and 5 skimming around but doing all the exercises religiously with IntelliJ. Folding was hurting my brain but I now think I understand it. Took days. So I have a long way to go. Reassuring to have found a space to share the journey with kindred spirits.
    j
    r
    • 3
    • 7
  • p

    pajatopmr

    03/28/2021, 12:51 PM
    About exercise 3.12 (Hard): this problem was a beast. I spent the allotted hour on it then looked at the solutions, all three of them. The first two (not demystified) were inscrutable. The demystified version was a God-send and reveals a mechanism for unraveling inscrutable FP solutions: use meaningful names rather than the terse
    z
    and
    f
    .
    šŸš€ 1
    m
    • 2
    • 5
  • j

    julian

    03/28/2021, 7:51 PM
    @pajatopmr Just curious, have you looked at Bartosz Milewski’s book on category theory? https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/
    p
    • 2
    • 2
  • j

    julian

    03/28/2021, 8:11 PM
    Someone asked on #arrow about having a reference project for using Arrow in Android development. https://kotlinlang.slack.com/archives/C5UPMM0A0/p1616411097027700
  • p

    pajatopmr

    04/19/2021, 9:23 PM
    What's the general consensus on the book using KotlinTest (correct me if I'm wrong, but I now believe KotlinTest has morphed into Kotest)?
    j
    m
    • 3
    • 13
  • g

    Giovan

    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 (
    when
    ) 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 {
            it["Note"]?.cast<Resource.Note>()?.insert()
            it["Tag"]?.cast<Resource.Tag>()?.insert()
            it["Character"]?.cast<Resource.Character>()?.insert()
            it["Address"]?.cast<Resource.Address>()?.insert()
        }
    }
    
    fun main() {
        pullResource().map(Resource::toDecrypt).filter(Resource::checkLegal).let(::insertDB)
    }
    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.
    j
    • 2
    • 2
  • r

    Randall Perry

    09/22/2021, 5:56 PM
    Exercise 6.7: confused by answer syntax
  • r

    Randall Perry

    09/22/2021, 6:02 PM
    Copy code
    fun <A> sequence(fs: FList<Rand<A>>): Rand<FList<A>> = { rng ->
        when (fs) {
            is FList.Nil -> unit(FList.empty<A>())(rng)
            is FList.Cons -> {
                val (a, nrng) = fs.head(rng)
                val (xa, frng) = sequence(fs.tail)(nrng)
                FList.Cons(a, xa) to frng
            }
        }
    }
    This 1st answer was said to be not stack-safe, and the correct solution uses foldRight. But, I’m trying to understand the syntax. They have the ā€˜rng’ or the ā€˜nrng’ var enclosed in parantheses following the two return values:
    Copy code
    unit(FList.empty<A>())(rng)
    Copy code
    sequence(fs.tail)(nrng)
    What does this mean? Is invoke being called via the parantheses? Or is the RNG type getting passed thru?
    j
    • 2
    • 3
  • d

    dnowak

    11/29/2021, 12:35 AM
    Hi, I’ve tried my best to convert examples from the book ā€œDomain Modeling Made Functional Tackle Software Complexity with Domain-Driven Design and F#ā€ to Kotlin based on Arrow. The result is here:Ā https://github.com/dnowak/domain-modeling-made-functional-in-kotlin I would be grateful for any hints on making the code more idiomatic regarding FP & Arrow.
    šŸ‘ 3
    j
    • 2
    • 1
  • r

    Race

    02/27/2022, 2:02 AM
    I am trying to filter a list based on a condition that a property inside the list is an enum type. But I get an error on the filter function
    Copy code
    Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
    l
    • 2
    • 1
  • r

    Race

    02/27/2022, 2:03 AM
    Can anyone tell me what’s wrong with my code? Playground link: https://pl.kotl.in/aRLlyLmso
    t
    • 2
    • 4
  • a

    Alexandre A Barbosa

    01/20/2023, 6:48 PM
    Awesome! Thank you @julian
    šŸ˜„ 1
  • a

    Alexandre A Barbosa

    06/01/2023, 8:20 PM
    hey channel. Beginner with Kotlin here… I really appreciate if someone here could, please, share a tip for removing this duplicity of code. The data class for Entities and CrudRepository are similar but are different business domain.
    Copy code
    when(notificationType) {
        "x" -> npRepository.findByIdOrNull(notificationId)?.let {
            npsRepository.findByXId(notificationId, userId)
                .takeIf { it.isNotEmpty() }
                ?.map { it.apply { isRead = notificationRead } }
                ?.let { npsRepository.saveAll(it) }
                ?: npsRepository.save(
                    NPS(
                        notificationPlatformId = notificationId,
                        userId = userId,
                        isRead = notificationRead
                    )
                )
        } ?: logAndThrowNotFound(notificationType, notificationId, throwNotFound)
    
        "y" ->
            ntRepository.findByIdOrNull(notificationId)?.let {
                ntsRepository.findByXId(notificationId, userId)
                    .takeIf { it.isNotEmpty() }
                    ?.map { it.apply { isRead = notificationRead } }
                    ?.let { ntsRepository.saveAll(it)}
                    ?: ntsRepository.save(NTS(
                            notificationTenantId = notificationId,
                            userId = userId,
                            isRead = notificationRead
                        )
                    )
            } ?: logAndThrowNotFound(notificationType, notificationId, throwNotFound)
    ...
    }
    b
    t
    • 3
    • 4