Arrow of outrageous fortune
Functional Programming in Kotlin
David Rawson
class Author(val firstName: String,
    val lastName: String) extends Comparable[Author] {
  override def compareTo(that: Author) = {
    val lastNameComp = this.lastName compareTo that.lastName
    if (lastNameComp != 0) lastNameComp
    else this.firstName compareTo that.firstName
  }
}
object Author {
  def loadAuthorsFromFile(file: java.io.File): List[Author] = ???
}class Author(val firstName: String,
    val lastName: String) extends Comparable[Author] {
  override def compareTo(that: Author) = {
    val lastNameComp = this.lastName compareTo that.lastName
    if (lastNameComp != 0) lastNameComp
    else this.firstName compareTo that.firstName
  }
}
object Author {
  def loadAuthorsFromFile(file: java.io.File): List[Author] = ???
}import java.io.File
class Author(
    val firstName: String,
    val lastName: String
) : Comparable<Author> {
    override fun compareTo(that: Author) {
        val lastNameComp = this.lastName.compareTo(that.lastName)
        return if (lastNameComp != 0) {
            lastNameComp
        } else {
            this.firstName.compareTo(that.firstName)
        }
    }
}
object Authors {
    fun loadAuthorsFromFile(file: File): List<Author> = TODO()
}import java.io.File
class Author(
    val firstName: String,
    val lastName: String
) : Comparable<Author> {
    override fun compareTo(that: Author) = compareValuesBy(
        this,
        that,
        Author::lastName,
        Author::firstName
    )
}
object Authors {
    fun loadAuthorsFromFile(file: File): List<Author> = TODO()
}plugins {
    java
    kotlin("jvm") version "1.4.10"
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
    mavenCentral()
}
dependencies {
    implementation(kotlin("stdlib"))
    testCompile("junit", "junit", "4.12")
}
fun main() {
    val immutable = listOf(1, 2, 3)
    val mutable = mutableListOf(1, 2, 3)
    val david = Person(Name("David"), Age(21))
    val olderDavid = david.copy(age = Age(22))
}https://arrow-kt.io/
Our initial positive impressions of Arrow were confirmed when using it to build applications that are now in production.
core
fx
optics
meta
Typeclass-o-pedia
Typeclass-o-pedia
Typeclass-o-pedia
Typeclass-o-pedia
Typeclass-o-pedia
Typeclass-o-pedia
Error handling
data class Name(val name: String)
data class Age(val age: Int)
data class Person(val name: Name, val age: Age)
object TestClassic {
    fun makeName(name: String?): Name {
        if (name == null || name == "") {
            throw IllegalArgumentException("Name cannot be null or empty")
        }
        return Name(name)
    }
    fun makeAge(age: String): Age {
        val parsedAge = age.toInt()
        require(0 <= parsedAge) {
            "Ages must be non-negative"
        }
        return Age(parsedAge)
    }
}
fun main(args: Array<String>) {
    try {
        val name = TestClassic.makeName(args[0])
        val age = TestClassic.makeAge(args[1])
        val person = Person(name, age)
        println(person)
    } catch (e: Exception) {
        println("Could not make a person!")
    }
}import arrow.core.Either
object TestEither {
    fun makeName(name: String?): Either<Throwable, Name> {
        return when (name) {
            null, "" -> return Either.Left(IllegalArgumentException())
            else -> Either.Right(Name(name))
        }
    }
    fun makeAge(age: String): Either<Throwable, Age> =
        Either.catch {
            age.toInt()
        }.flatMap {
            when {
                it <= 0 -> Either.Left(IllegalArgumentException())
                else -> Either.Right(it)
            }
        }.map {
            Age(it)
        }
}import arrow.core.Either
fun main(args: Array<String>) {
    TestEither.makeName(args[0]).flatMap { name ->
        TestEither.makeAge(args[1]).map { age ->
            Person(name, age)
        }
    }.fold(
        ifLeft = {
            "Could not make a person!"
        },
        ifRight = {
            it.toString()
        }
    ).let {
        println(it)
    }
}import arrow.core.computations.either
suspend fun main(args: Array<String>) {
    either<Throwable, Person> {
        val name = TestEither.makeName(args[0]).bind()
        val age = TestEither.makeAge(args[1]).bind()
        Person(name, age)
    }.fold(
        ifLeft = {
                 "Could not make a person!"
        } ,
        ifRight = {
            it
        }
    ).let {
        println(it)
    }
}https://medium.com/@heyitsmohit/writing-kotlin-compiler-plugin-with-arrow-meta-cf7b3689aa3e
https://medium.com/@heyitsmohit/writing-kotlin-compiler-plugin-with-arrow-meta-cf7b3689aa3e
intercepts
data class Age(val age: Int)
object TestClassic {
    fun makeAge(age: String): Age {
        val parsedAge = age.toInt()
        require(0 < parsedAge) {
            "Ages must be positive"
        }
        return Age(parsedAge)
    }
}
data class PositiveInt(val value: Int) {
    init {
        require(0 < value) {
            "Should be positive"
        }
    }
}@Refinement
inline class PositiveInt(val value: Int)  {
    companion object : Refined<Int, PositiveInt> {
        override val target : (Int) -> PositiveInt = ::PositiveInt
        override val validate: Int.() -> Map<String, Boolean> = {
            mapOf(
                "Should be > 0" to (this > 0)
            )
        }
    }
}
@Coercion
fun Int.positive(): PositiveInt? =
    PositiveInt.from(this)