diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml
index c5b7fed951..92a643e458 100644
--- a/kotlin-libraries/pom.xml
+++ b/kotlin-libraries/pom.xml
@@ -87,6 +87,13 @@
h2
${h2database.version}
+
+
+ io.arrow-kt
+ arrow-core
+ 0.7.3
+
+
diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt
new file mode 100644
index 0000000000..75dfb9a2a4
--- /dev/null
+++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt
@@ -0,0 +1,54 @@
+package com.baeldung.kotlin.arrow
+
+import arrow.core.Either
+import arrow.core.filterOrElse
+import kotlin.math.sqrt
+
+class FunctionalErrorHandlingWithEither {
+
+ sealed class ComputeProblem {
+ object OddNumber : ComputeProblem()
+ object NotANumber : ComputeProblem()
+ }
+
+ fun parseInput(s : String) : Either = Either.cond(s.toIntOrNull() != null, {-> s.toInt()}, {->ComputeProblem.NotANumber} )
+
+ fun isEven(x : Int) : Boolean = x % 2 == 0
+
+ fun biggestDivisor(x: Int) : Int = biggestDivisor(x, 2)
+
+ fun biggestDivisor(x : Int, y : Int) : Int {
+ if(x == y){
+ return 1;
+ }
+ if(x % y == 0){
+ return x / y;
+ }
+ return biggestDivisor(x, y+1)
+ }
+
+ fun isSquareNumber(x : Int) : Boolean {
+ val sqrt: Double = sqrt(x.toDouble())
+ return sqrt % 1.0 == 0.0
+ }
+
+ fun computeWithEither(input : String) : Either {
+ return parseInput(input)
+ .filterOrElse(::isEven) {->ComputeProblem.OddNumber}
+ .map (::biggestDivisor)
+ .map (::isSquareNumber)
+ }
+
+ fun computeWithEitherClient(input : String) {
+ val computeWithEither = computeWithEither(input)
+
+ when(computeWithEither){
+ is Either.Right -> "The greatest divisor is square number: ${computeWithEither.b}"
+ is Either.Left -> when(computeWithEither.a){
+ is ComputeProblem.NotANumber -> "Wrong input! Not a number!"
+ is ComputeProblem.OddNumber -> "It is an odd number!"
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt
new file mode 100644
index 0000000000..5fddd1d88e
--- /dev/null
+++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt
@@ -0,0 +1,46 @@
+package com.baeldung.kotlin.arrow
+
+import arrow.core.None
+import arrow.core.Option
+import arrow.core.Some
+import kotlin.math.sqrt
+
+class FunctionalErrorHandlingWithOption {
+
+ fun parseInput(s : String) : Option = Option.fromNullable(s.toIntOrNull())
+
+ fun isEven(x : Int) : Boolean = x % 2 == 0
+
+ fun biggestDivisor(x: Int) : Int = biggestDivisor(x, 2)
+
+ fun biggestDivisor(x : Int, y : Int) : Int {
+ if(x == y){
+ return 1;
+ }
+ if(x % y == 0){
+ return x / y;
+ }
+ return biggestDivisor(x, y+1)
+ }
+
+ fun isSquareNumber(x : Int) : Boolean {
+ val sqrt: Double = sqrt(x.toDouble())
+ return sqrt % 1.0 == 0.0
+ }
+
+ fun computeWithOption(input : String) : Option {
+ return parseInput(input)
+ .filter(::isEven)
+ .map(::biggestDivisor)
+ .map(::isSquareNumber)
+ }
+
+ fun computeWithOptionClient(input : String) : String{
+ val computeOption = computeWithOption(input)
+
+ return when(computeOption){
+ is None -> "Not an even number!"
+ is Some -> "The greatest divisor is square number: ${computeOption.t}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt
new file mode 100644
index 0000000000..692425ee07
--- /dev/null
+++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt
@@ -0,0 +1,143 @@
+package com.baeldung.kotlin.arrow
+
+import arrow.core.*
+import org.junit.Assert
+import org.junit.Test
+
+class FunctionalDataTypes {
+
+ @Test
+ fun whenIdCreated_thanValueIsPresent(){
+ val id = Id("foo")
+ val justId = Id.just("foo");
+
+ Assert.assertEquals("foo", id.extract())
+ Assert.assertEquals(justId, id)
+ }
+
+ fun length(s : String) : Int = s.length
+
+ fun isBigEnough(i : Int) : Boolean = i > 10
+
+ @Test
+ fun whenIdCreated_thanMapIsAssociative(){
+ val foo = Id("foo")
+
+ val map1 = foo.map(::length)
+ .map(::isBigEnough)
+ val map2 = foo.map { s -> isBigEnough(length(s)) }
+
+ Assert.assertEquals(map1, map2)
+ }
+
+ fun lengthId(s : String) : Id = Id.just(length(s))
+
+ fun isBigEnoughId(i : Int) : Id = Id.just(isBigEnough(i))
+
+ @Test
+ fun whenIdCreated_thanFlatMapIsAssociative(){
+ val bar = Id("bar")
+
+ val flatMap = bar.flatMap(::lengthId)
+ .flatMap(::isBigEnoughId)
+ val flatMap1 = bar.flatMap { s -> lengthId(s).flatMap(::isBigEnoughId) }
+
+ Assert.assertEquals(flatMap, flatMap1)
+ }
+
+ @Test
+ fun whenOptionCreated_thanValueIsPresent(){
+ val factory = Option.just(42)
+ val constructor = Option(42)
+ val emptyOptional = Option.empty()
+ val fromNullable = Option.fromNullable(null)
+
+ Assert.assertEquals(42, factory.getOrElse { -1 })
+ Assert.assertEquals(factory, constructor)
+ Assert.assertEquals(emptyOptional, fromNullable)
+ }
+
+ @Test
+ fun whenOptionCreated_thanConstructorDifferFromFactory(){
+ val constructor : Option = Option(null)
+ val fromNullable : Option = Option.fromNullable(null)
+
+ try{
+ constructor.map { s -> s!!.length }
+ Assert.fail()
+ } catch (e : KotlinNullPointerException){
+ fromNullable.map { s->s!!.length }
+ }
+ Assert.assertNotEquals(constructor, fromNullable)
+ }
+
+ fun wrapper(x : Integer?) : Option = if (x == null) Option.just(-1) else Option.just(x.toInt())
+
+ @Test
+ fun whenOptionFromNullableCreated_thanItBreaksLeftIdentity(){
+ val optionFromNull = Option.fromNullable(null)
+
+ Assert.assertNotEquals(optionFromNull.flatMap(::wrapper), wrapper(null))
+ }
+
+ @Test
+ fun whenEitherCreated_thanOneValueIsPresent(){
+ val rightOnly : Either = Either.right(42)
+ val leftOnly : Either = Either.left("foo")
+
+ Assert.assertTrue(rightOnly.isRight())
+ Assert.assertTrue(leftOnly.isLeft())
+ Assert.assertEquals(42, rightOnly.getOrElse { -1 })
+ Assert.assertEquals(-1, leftOnly.getOrElse { -1 })
+
+ Assert.assertEquals(0, rightOnly.map { it % 2 }.getOrElse { -1 })
+ Assert.assertEquals(-1, leftOnly.map { it % 2 }.getOrElse { -1 })
+ Assert.assertTrue(rightOnly.flatMap { Either.Right(it % 2) }.isRight())
+ Assert.assertTrue(leftOnly.flatMap { Either.Right(it % 2) }.isLeft())
+ }
+
+ @Test
+ fun whenEvalNowUsed_thenMapEvaluatedLazily(){
+ val now = Eval.now(1)
+ Assert.assertEquals(1, now.value())
+
+ var counter : Int = 0
+ val map = now.map { x -> counter++; x+1 }
+ Assert.assertEquals(0, counter)
+
+ val value = map.value()
+ Assert.assertEquals(2, value)
+ Assert.assertEquals(1, counter)
+ }
+
+ @Test
+ fun whenEvalLaterUsed_theResultIsMemoized(){
+ var counter : Int = 0
+ val later = Eval.later { counter++; counter }
+ Assert.assertEquals(0, counter)
+
+ val firstValue = later.value()
+ Assert.assertEquals(1, firstValue)
+ Assert.assertEquals(1, counter)
+
+ val secondValue = later.value()
+ Assert.assertEquals(1, secondValue)
+ Assert.assertEquals(1, counter)
+ }
+
+ @Test
+ fun whenEvalAlwaysUsed_theResultIsNotMemoized(){
+ var counter : Int = 0
+ val later = Eval.always { counter++; counter }
+ Assert.assertEquals(0, counter)
+
+ val firstValue = later.value()
+ Assert.assertEquals(1, firstValue)
+ Assert.assertEquals(1, counter)
+
+ val secondValue = later.value()
+ Assert.assertEquals(2, secondValue)
+ Assert.assertEquals(2, counter)
+ }
+
+}
\ No newline at end of file
diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt
new file mode 100644
index 0000000000..47fbf825a0
--- /dev/null
+++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt
@@ -0,0 +1,68 @@
+package com.baeldung.kotlin.arrow
+
+import arrow.core.Either
+import com.baeldung.kotlin.arrow.FunctionalErrorHandlingWithEither.ComputeProblem.NotANumber
+import com.baeldung.kotlin.arrow.FunctionalErrorHandlingWithEither.ComputeProblem.OddNumber
+import org.junit.Assert
+import org.junit.Test
+
+class FunctionalErrorHandlingWithEitherTest {
+
+ val operator = FunctionalErrorHandlingWithEither()
+
+ @Test
+ fun givenInvalidInput_whenComputeInvoked_NotANumberIsPresent(){
+ val computeWithEither = operator.computeWithEither("bar")
+
+ Assert.assertTrue(computeWithEither.isLeft())
+ when(computeWithEither){
+ is Either.Left -> when(computeWithEither.a){
+ NotANumber -> "Ok."
+ else -> Assert.fail()
+ }
+ else -> Assert.fail()
+ }
+ }
+
+ @Test
+ fun givenOddNumberInput_whenComputeInvoked_OddNumberIsPresent(){
+ val computeWithEither = operator.computeWithEither("121")
+
+ Assert.assertTrue(computeWithEither.isLeft())
+ when(computeWithEither){
+ is Either.Left -> when(computeWithEither.a){
+ OddNumber -> "Ok."
+ else -> Assert.fail()
+ }
+ else -> Assert.fail()
+ }
+ }
+
+ @Test
+ fun givenEvenNumberWithoutSquare_whenComputeInvoked_OddNumberIsPresent(){
+ val computeWithEither = operator.computeWithEither("100")
+
+ Assert.assertTrue(computeWithEither.isRight())
+ when(computeWithEither){
+ is Either.Right -> when(computeWithEither.b){
+ false -> "Ok."
+ else -> Assert.fail()
+ }
+ else -> Assert.fail()
+ }
+ }
+
+ @Test
+ fun givenEvenNumberWithSquare_whenComputeInvoked_OddNumberIsPresent(){
+ val computeWithEither = operator.computeWithEither("98")
+
+ Assert.assertTrue(computeWithEither.isRight())
+ when(computeWithEither){
+ is Either.Right -> when(computeWithEither.b){
+ true -> "Ok."
+ else -> Assert.fail()
+ }
+ else -> Assert.fail()
+ }
+ }
+}
\ No newline at end of file
diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt
new file mode 100644
index 0000000000..3ca4cd033f
--- /dev/null
+++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt
@@ -0,0 +1,34 @@
+package com.baeldung.kotlin.arrow
+
+import org.junit.Assert
+import org.junit.Test
+
+class FunctionalErrorHandlingWithOptionTest {
+
+ val operator = FunctionalErrorHandlingWithOption()
+
+ @Test
+ fun givenInvalidInput_thenErrorMessageIsPresent(){
+ val useComputeOption = operator.computeWithOptionClient("foo")
+ Assert.assertEquals("Not an even number!", useComputeOption)
+ }
+
+ @Test
+ fun givenOddNumberInput_thenErrorMessageIsPresent(){
+ val useComputeOption = operator.computeWithOptionClient("539")
+ Assert.assertEquals("Not an even number!",useComputeOption)
+ }
+
+ @Test
+ fun givenEvenNumberInputWithNonSquareNum_thenFalseMessageIsPresent(){
+ val useComputeOption = operator.computeWithOptionClient("100")
+ Assert.assertEquals("The greatest divisor is square number: false",useComputeOption)
+ }
+
+ @Test
+ fun givenEvenNumberInputWithSquareNum_thenTrueMessageIsPresent(){
+ val useComputeOption = operator.computeWithOptionClient("242")
+ Assert.assertEquals("The greatest divisor is square number: true",useComputeOption)
+ }
+
+}
\ No newline at end of file