Book Image

Functional Kotlin

Book Image

Functional Kotlin

Overview of this book

Functional programming makes your application faster, improves performance, and increases your productivity. Kotlin supports many of the popular and advanced functional features of functional languages. This book will cover the A-Z of functional programming in Kotlin. This book bridges the language gap for Kotlin developers by showing you how to create and consume functional constructs in Kotlin. We also bridge the domain gap by showing how functional constructs can be applied in business scenarios. We’ll take you through lambdas, pattern matching, immutability, and help you develop a deep understanding of the concepts and practices of functional programming. If you want learn to address problems using Recursion, Koltin has support for it as well. You’ll also learn how to use the funKtionale library to perform currying and lazy programming and more. Finally, you’ll learn functional design patterns and techniques that will make you a better programmer.By the end of the book, you will be more confident in your functional programming skills and will be able to apply them while programming in Kotlin.
Table of Contents (22 chapters)
Title Page
Copyright and Credits
Dedication
Packt Upsell
Contributors
Preface
Index

Kotlin's type system


Type systems are a set of rules that determine the type of a language construct.

A (good) type system will help you with:

  • Making sure that the constituent parts of your program are connected in a consistent way
  • Understanding your program (by reducing your cognitive load)
  • Expressing business rules
  • Automatic low-level optimizations

We have already covered enough ground to understand Kotlin's type system.

The Any type

All types in Kotlin extend from the Any type (hold on a second, actually this isn't true but for the sake of the explanation, bear with me).

Every class and interface that we create implicitly extends Any. So, if we write a method that takes Any as a parameter, it will receive any value:

fun main(args: Array<String>) {

    val myAlmondCupcake = Cupcake.almond()

    val anyMachine = object : Machine<Any> {
      override fun process(product: Any) {
        println(product.toString())
      }
    }

    anyMachine.process(3)

    anyMachine.process("")

    anyMachine.process(myAlmondCupcake)    
}

What about a nullable value? Let's have a look at it:

fun main(args: Array<String>) {

    val anyMachine = object : Machine<Any> {
      override fun process(product: Any) {
        println(product.toString())
      }
    }

    val nullableCupcake: Cupcake? = Cupcake.almond()

    anyMachine.process(nullableCupcake) //Error:(32, 24) Kotlin: Type mismatch: inferred type is Cupcake? but Any was expected
}

Any is the same as any other type and also has a nullable counterpart, Any?Any extends from Any?. So, in the end, Any? is the top class of Kotlin's type system hierarchy.

Minimum common types

Due to its type inference and expression evaluation, sometimes there are expressions in Kotlin where it is not clear which type is being returned. Most languages resolve this problem by returning the minimum common type between the possible type options. Kotlin takes a different route.

Let's take a look at an example of an ambiguous expression:

fun main(args: Array<String>) {
    val nullableCupcake: Cupcake? = Cupcake.almond()

    val length = nullableCupcake?.eat()?.length ?: ""
}

What type does length have? Int or String? No, length value's type is Any. Pretty logical. The minimum common type between Int and String is Any. So far, so good. Let's look at the following code now:

val length = nullableCupcake?.eat()?.length ?: 0.0

Following that logic, in this case, length should have the Number type (the common type between Int and Double), shouldn't it?

Wrong, length is still Any. Kotlin doesn't search for the minimum common type in these situations. If you want a specific type, it must be explicitly declared:

val length: Number = nullableCupcake?.eat()?.length ?: 0.0

The Unit type

Kotlin doesn't have methods with void return (as Java or C do). Instead, a method (or, to be precise, an expression) could have a Unit type.

A Unit type means that the expression is called for its side effects, rather than its return. The classic example of a Unit expression is println(), a method invoked just for its side effects.

Unit, like any other Kotlin type, extends from Any and could be nullable. Unit? looks strange and unnecessary, but is needed to keep consistency with the type system. Having a consistent type system have several advantages, including better compilation times and tooling:

anyMachine.process(Unit)

The Nothing type

Nothing is the type that sits at the bottom of the entire Kotlin hierarchy. Nothing extends all Kotlin types, including Nothing?.

But, why do we need a Nothing and Nothing? types?

Nothing represents an expression that can't be executed (basically throwing exceptions):

val result: String = nullableCupcake?.eat() ?: throw RuntimeException() // equivalent to nullableCupcake!!.eat()

On one hand of the Elvis operator, we have a String. On the other hand, we have Nothing. Because the common type between String and Nothing is String (instead of Any), the value result is a String.

Nothing also has a special meaning for the compiler. Once a Nothing type is returned on an expression, the lines after that are marked as unreachable.

Nothing? is the type of a null value:

val x: Nothing? = null

val nullsList: List<Nothing?> = listOf(null)