├── .gitignore ├── .travis.yml ├── README.adoc ├── examples └── kotlingradle │ ├── MyMultipleProject │ ├── build.gradle.kts │ ├── client │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── kotlin │ │ │ └── com │ │ │ └── mydomain │ │ │ └── mymultipleproject │ │ │ └── client │ │ │ └── main │ │ │ └── Client.kt │ ├── common │ │ ├── build.gradle.kts │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── mydomain │ │ │ │ │ └── mymultipleproject │ │ │ │ │ └── common │ │ │ │ │ └── MyJavaLibrary.java │ │ │ └── kotlin │ │ │ │ └── com │ │ │ │ └── mydomain │ │ │ │ └── mymultipleproject │ │ │ │ └── common │ │ │ │ ├── MaxMultiple.kt │ │ │ │ ├── MyFile.kt │ │ │ │ ├── MyKotlinLibrary.kt │ │ │ │ ├── example00 │ │ │ │ └── MyKotlinLibrary.kt │ │ │ │ ├── example01 │ │ │ │ └── MyKotlinLibrary.kt │ │ │ │ ├── example02 │ │ │ │ └── MyKotlinLibrary.kt │ │ │ │ ├── example03 │ │ │ │ └── SameLettersStrings.kt │ │ │ │ ├── example04 │ │ │ │ └── SameLettersStrings.kt │ │ │ │ ├── example05 │ │ │ │ └── SameLettersStrings.kt │ │ │ │ ├── example06 │ │ │ │ └── SameLettersStrings.kt │ │ │ │ └── example07 │ │ │ │ └── SameLettersStrings.kt │ │ │ └── test │ │ │ └── kotlin │ │ │ └── com │ │ │ └── mydomain │ │ │ └── mymultipleproject │ │ │ └── common │ │ │ ├── MyJavaLibraryTest.kt │ │ │ ├── MyKotlinLibraryTest.kt │ │ │ ├── example00 │ │ │ └── MyKotlinLibraryKtTest.kt │ │ │ ├── example01 │ │ │ └── MyKotlinLibraryTest.kt │ │ │ ├── example02 │ │ │ └── MyKotlinLibraryTest.kt │ │ │ ├── example03 │ │ │ ├── SameLettersStringKtTest.kt │ │ │ └── StringGenerator.kt │ │ │ ├── example04 │ │ │ ├── ListGenerator.kt │ │ │ ├── SameLettersStringKtTest.kt │ │ │ └── StringGenerator.kt │ │ │ ├── example05 │ │ │ ├── ListGenerator.kt │ │ │ ├── MapGenerator.kt │ │ │ ├── SameLettersStringKtTest.kt │ │ │ ├── StringGenerator.kt │ │ │ └── UpdateMapTest.kt │ │ │ └── example06 │ │ │ ├── CharGenerator.kt │ │ │ ├── ListGenerator.kt │ │ │ ├── MapGenerator.kt │ │ │ ├── SameLettersStringKtTest.kt │ │ │ ├── StringGenerator.kt │ │ │ └── UpdateMapTest.kt │ ├── server │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── mydomain │ │ │ └── mymultipleproject │ │ │ └── server │ │ │ └── main │ │ │ └── Server.java │ └── settings.gradle.kts │ ├── MySimpleProject │ ├── build.gradle.kts │ ├── gradlew │ ├── gradlew.bat │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── mydomain │ │ │ └── mysimpleproject │ │ │ └── MyClass.java │ │ └── kotlin │ │ └── com │ │ └── mydomain │ │ └── mysimpleproject │ │ └── Main.kt │ └── README.md ├── fpinkotlin-parent ├── README.adoc ├── build.gradle.kts ├── fpinkotlin-actors │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── actors │ │ ├── listing01to03 │ │ └── Actor.kt │ │ ├── listing04to07 │ │ └── PingPong.kt │ │ ├── listing08to12 │ │ ├── Actor.kt │ │ ├── Manager.kt │ │ ├── Worker.kt │ │ └── WorkersExample.kt │ │ ├── listing13 │ │ ├── Actor.kt │ │ ├── Manager.kt │ │ ├── Worker.kt │ │ └── WorkersExample.kt │ │ ├── listing14 │ │ ├── Actor.kt │ │ ├── Manager.kt │ │ ├── Receiver.kt │ │ ├── Worker.kt │ │ └── WorkersExample.kt │ │ ├── listing15 │ │ ├── Heap.kt │ │ ├── List.kt │ │ ├── Option.kt │ │ ├── Result.kt │ │ └── WorkersExample.kt │ │ ├── listing16 │ │ └── WorkersExample.kt │ │ ├── listing17 │ │ └── WorkerExample.kt │ │ ├── listing18 │ │ └── WorkersChannel.kt │ │ ├── listing19 │ │ └── WorkersChannel.kt │ │ ├── listing20 │ │ ├── Deque.kt │ │ └── WorkersChannel.kt │ │ └── listing21 │ │ └── WorkersChannel.kt ├── fpinkotlin-advancedlisthandling-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── advancedlisthandling │ │ │ ├── exercise01 │ │ │ └── List.kt │ │ │ ├── exercise02 │ │ │ └── List.kt │ │ │ ├── exercise03 │ │ │ └── List.kt │ │ │ ├── exercise04 │ │ │ └── List.kt │ │ │ ├── exercise05 │ │ │ └── List.kt │ │ │ ├── exercise06 │ │ │ └── List.kt │ │ │ ├── exercise07 │ │ │ └── List.kt │ │ │ ├── exercise08 │ │ │ └── List.kt │ │ │ ├── exercise09 │ │ │ └── List.kt │ │ │ ├── exercise10 │ │ │ └── List.kt │ │ │ ├── exercise11 │ │ │ └── List.kt │ │ │ ├── exercise12 │ │ │ └── List.kt │ │ │ ├── exercise13 │ │ │ └── List.kt │ │ │ ├── exercise14 │ │ │ └── List.kt │ │ │ ├── exercise15 │ │ │ └── List.kt │ │ │ ├── exercise16 │ │ │ └── List.kt │ │ │ ├── exercise17 │ │ │ └── List.kt │ │ │ ├── exercise18 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise19 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise20 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise21 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise22 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise23 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ └── exercise24 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── advancedlisthandling │ │ ├── exercise01 │ │ └── ListTest.kt │ │ ├── exercise02 │ │ └── ListTest.kt │ │ ├── exercise03 │ │ └── ListTest.kt │ │ ├── exercise04 │ │ └── ListTest.kt │ │ ├── exercise05 │ │ └── ListTest.kt │ │ ├── exercise06 │ │ └── ListTest.kt │ │ ├── exercise07 │ │ └── ListTest.kt │ │ ├── exercise08 │ │ └── ListTest.kt │ │ ├── exercise09 │ │ └── ListTest.kt │ │ ├── exercise10 │ │ └── ListTest.kt │ │ ├── exercise11 │ │ └── ListTest.kt │ │ ├── exercise12 │ │ └── ListTest.kt │ │ ├── exercise13 │ │ └── ListTest.kt │ │ ├── exercise14 │ │ └── ListTest.kt │ │ ├── exercise15 │ │ └── ListTest.kt │ │ ├── exercise16 │ │ └── ListTest.kt │ │ ├── exercise17 │ │ └── ListTest.kt │ │ ├── exercise18 │ │ └── ListTest.kt │ │ ├── exercise19 │ │ └── ListTest.kt │ │ ├── exercise20 │ │ └── ListTest.kt │ │ ├── exercise21 │ │ └── ListTest.kt │ │ ├── exercise22 │ │ └── ListTest.kt │ │ ├── exercise23 │ │ ├── ListTest.kt │ │ └── SerialParallelFoldLeftBenchmark.kt │ │ └── exercise24 │ │ ├── ListTest.kt │ │ └── SerialParallelFoldLeftBenchmark.kt ├── fpinkotlin-advancedlisthandling-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── advancedlisthandling │ │ │ ├── exercise01 │ │ │ └── List.kt │ │ │ ├── exercise02 │ │ │ └── List.kt │ │ │ ├── exercise03 │ │ │ └── List.kt │ │ │ ├── exercise04 │ │ │ └── List.kt │ │ │ ├── exercise05 │ │ │ └── List.kt │ │ │ ├── exercise06 │ │ │ └── List.kt │ │ │ ├── exercise07 │ │ │ └── List.kt │ │ │ ├── exercise08 │ │ │ └── List.kt │ │ │ ├── exercise09 │ │ │ └── List.kt │ │ │ ├── exercise10 │ │ │ └── List.kt │ │ │ ├── exercise11 │ │ │ └── List.kt │ │ │ ├── exercise12 │ │ │ └── List.kt │ │ │ ├── exercise13 │ │ │ └── List.kt │ │ │ ├── exercise14 │ │ │ └── List.kt │ │ │ ├── exercise15 │ │ │ └── List.kt │ │ │ ├── exercise16 │ │ │ └── List.kt │ │ │ ├── exercise17 │ │ │ └── List.kt │ │ │ ├── exercise18 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise19 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise20 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise21 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise22 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise23 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ └── exercise24 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── advancedlisthandling │ │ ├── exercise01 │ │ └── ListTest.kt │ │ ├── exercise02 │ │ └── ListTest.kt │ │ ├── exercise03 │ │ └── ListTest.kt │ │ ├── exercise04 │ │ └── ListTest.kt │ │ ├── exercise05 │ │ └── ListTest.kt │ │ ├── exercise06 │ │ └── ListTest.kt │ │ ├── exercise07 │ │ └── ListTest.kt │ │ ├── exercise08 │ │ └── ListTest.kt │ │ ├── exercise09 │ │ └── ListTest.kt │ │ ├── exercise10 │ │ └── ListTest.kt │ │ ├── exercise11 │ │ └── ListTest.kt │ │ ├── exercise12 │ │ └── ListTest.kt │ │ ├── exercise13 │ │ └── ListTest.kt │ │ ├── exercise14 │ │ └── ListTest.kt │ │ ├── exercise15 │ │ └── ListTest.kt │ │ ├── exercise16 │ │ └── ListTest.kt │ │ ├── exercise17 │ │ └── ListTest.kt │ │ ├── exercise18 │ │ └── ListTest.kt │ │ ├── exercise19 │ │ └── ListTest.kt │ │ ├── exercise20 │ │ └── ListTest.kt │ │ ├── exercise21 │ │ └── ListTest.kt │ │ ├── exercise22 │ │ └── ListTest.kt │ │ ├── exercise23 │ │ ├── ListTest.kt │ │ └── SerialParallelFoldLeftBenchmark.kt │ │ └── exercise24 │ │ ├── ListTest.kt │ │ └── SerialParallelFoldLeftBenchmark.kt ├── fpinkotlin-advancedtrees-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── advancedtrees │ │ │ ├── common │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise01 │ │ │ └── Tree.kt │ │ │ ├── exercise02 │ │ │ ├── Map.kt │ │ │ ├── MapEntry.kt │ │ │ └── Tree.kt │ │ │ ├── exercise03 │ │ │ ├── Map.kt │ │ │ ├── MapEntry.kt │ │ │ └── Tree.kt │ │ │ ├── exercise04 │ │ │ ├── Map.kt │ │ │ ├── MapEntry.kt │ │ │ └── Tree.kt │ │ │ ├── exercise05 │ │ │ └── Heap.kt │ │ │ ├── exercise06 │ │ │ └── Heap.kt │ │ │ ├── exercise07 │ │ │ └── Heap.kt │ │ │ ├── exercise08 │ │ │ └── Heap.kt │ │ │ ├── exercise09 │ │ │ └── Heap.kt │ │ │ └── exercise10 │ │ │ └── Heap.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── advancedtrees │ │ ├── exercise01 │ │ └── TreeTest.kt │ │ ├── exercise02 │ │ ├── MapTest.kt │ │ └── NumbersToEnglish.kt │ │ ├── exercise03 │ │ ├── MapTest.kt │ │ └── NumbersToEnglish.kt │ │ ├── exercise04 │ │ ├── MapTest.kt │ │ └── NumbersToEnglish.kt │ │ ├── exercise05 │ │ └── HeapTest.kt │ │ ├── exercise06 │ │ └── HeapTest.kt │ │ ├── exercise07 │ │ └── HeapTest.kt │ │ ├── exercise08 │ │ └── HeapTest.kt │ │ ├── exercise09 │ │ └── HeapTest.kt │ │ └── exercise10 │ │ └── HeapTest.kt ├── fpinkotlin-advancedtrees-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── advancedtrees │ │ │ ├── common │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise01 │ │ │ └── Tree.kt │ │ │ ├── exercise02 │ │ │ ├── Map.kt │ │ │ ├── MapEntry.kt │ │ │ └── Tree.kt │ │ │ ├── exercise03 │ │ │ ├── Map.kt │ │ │ ├── MapEntry.kt │ │ │ └── Tree.kt │ │ │ ├── exercise04 │ │ │ ├── Map.kt │ │ │ ├── MapEntry.kt │ │ │ └── Tree.kt │ │ │ ├── exercise05 │ │ │ └── Heap.kt │ │ │ ├── exercise06 │ │ │ └── Heap.kt │ │ │ ├── exercise07 │ │ │ └── Heap.kt │ │ │ ├── exercise08 │ │ │ └── Heap.kt │ │ │ ├── exercise09 │ │ │ └── Heap.kt │ │ │ ├── exercise10 │ │ │ └── Heap.kt │ │ │ ├── listing01 │ │ │ └── Tree.kt │ │ │ ├── listing02 │ │ │ └── Map.kt │ │ │ └── listing03 │ │ │ └── Heap.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── advancedtrees │ │ ├── exercise01 │ │ └── TreeTest.kt │ │ ├── exercise02 │ │ ├── MapTest.kt │ │ ├── NumbersToEnglish.kt │ │ ├── NumbersToEnglishTest.kt │ │ ├── TreeBenchmark.kt │ │ └── TreeTest.kt │ │ ├── exercise03 │ │ ├── MapTest.kt │ │ └── NumbersToEnglish.kt │ │ ├── exercise04 │ │ ├── MapTest.kt │ │ └── NumbersToEnglish.kt │ │ ├── exercise05 │ │ └── HeapTest.kt │ │ ├── exercise06 │ │ └── HeapTest.kt │ │ ├── exercise07 │ │ └── HeapTest.kt │ │ ├── exercise08 │ │ └── HeapTest.kt │ │ ├── exercise09 │ │ └── HeapTest.kt │ │ └── exercise10 │ │ └── HeapTest.kt ├── fpinkotlin-common-test │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── generators │ │ └── Generators.kt ├── fpinkotlin-common │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── common │ │ ├── Heap.kt │ │ ├── Lazy.kt │ │ ├── List.kt │ │ ├── Option.kt │ │ ├── Result.kt │ │ └── Stream.kt ├── fpinkotlin-commonproblems │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── commonproblems │ │ │ ├── assertions │ │ │ └── listing01 │ │ │ │ └── Assertions.kt │ │ │ ├── properties │ │ │ ├── example01 │ │ │ │ └── Properties.kt │ │ │ ├── example02 │ │ │ │ └── Properties.kt │ │ │ ├── example03 │ │ │ │ └── Properties.kt │ │ │ ├── example04 │ │ │ │ └── Properties.kt │ │ │ ├── example05 │ │ │ │ └── Properties.kt │ │ │ └── example06 │ │ │ │ └── Properties.kt │ │ │ ├── retry │ │ │ └── example01 │ │ │ │ └── Retry.kt │ │ │ └── xml │ │ │ ├── step1 │ │ │ ├── ReadXmlFile.kt │ │ │ ├── empty.xml │ │ │ └── file.xml │ │ │ ├── step2 │ │ │ ├── ReadXmlFile.kt │ │ │ └── file.xml │ │ │ ├── step3 │ │ │ ├── ReadXmlFile.kt │ │ │ ├── TestXml.kt │ │ │ └── file.xml │ │ │ ├── step4 │ │ │ ├── ReadXmlFile.kt │ │ │ ├── TestXml.kt │ │ │ └── file.xml │ │ │ ├── step5 │ │ │ ├── ReadXmlFile.kt │ │ │ ├── TestXml.kt │ │ │ └── file.xml │ │ │ ├── step6 │ │ │ ├── ReadXmlFile.kt │ │ │ ├── TestXml.kt │ │ │ └── file.xml │ │ │ └── step7 │ │ │ ├── ReadXmlFile.kt │ │ │ ├── TestXml.kt │ │ │ └── file.xml │ │ └── resources │ │ └── config.properties ├── fpinkotlin-effects-exercises │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── effects │ │ ├── exercise01 │ │ ├── List.kt │ │ ├── Option.kt │ │ └── Result.kt │ │ ├── exercise02 │ │ ├── AbstractReader.kt │ │ ├── ConsoleReader.kt │ │ ├── Input.kt │ │ ├── Main.kt │ │ └── Person.kt │ │ ├── exercise03 │ │ ├── AbstractReader.kt │ │ ├── ConsoleReader.kt │ │ ├── FileReader.kt │ │ ├── Input.kt │ │ ├── Main.kt │ │ ├── Person.kt │ │ ├── ScriptReader.kt │ │ └── data.txt │ │ ├── exercise04 │ │ └── IO.kt │ │ ├── exercise05 │ │ ├── Console.kt │ │ └── IO.kt │ │ ├── exercise06 │ │ ├── Console.kt │ │ └── IO.kt │ │ ├── exercise07 │ │ ├── Console.kt │ │ └── IO.kt │ │ ├── exercise08 │ │ ├── Console.kt │ │ └── IO.kt │ │ └── exercise09 │ │ ├── Console.kt │ │ ├── IO.kt │ │ └── Main.kt ├── fpinkotlin-effects-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── effects │ │ │ ├── exercise01 │ │ │ ├── List.kt │ │ │ ├── Option.kt │ │ │ └── Result.kt │ │ │ ├── exercise02 │ │ │ ├── AbstractReader.kt │ │ │ ├── ConsoleReader.kt │ │ │ ├── Input.kt │ │ │ ├── Main.kt │ │ │ └── Person.kt │ │ │ ├── exercise03 │ │ │ ├── AbstractReader.kt │ │ │ ├── ConsoleReader.kt │ │ │ ├── FileReader.kt │ │ │ ├── Input.kt │ │ │ ├── Main.kt │ │ │ ├── Person.kt │ │ │ ├── ScriptReader.kt │ │ │ └── data.txt │ │ │ ├── exercise04 │ │ │ └── IO.kt │ │ │ ├── exercise05 │ │ │ ├── Console.kt │ │ │ └── IO.kt │ │ │ ├── exercise06 │ │ │ ├── Console.kt │ │ │ └── IO.kt │ │ │ ├── exercise07 │ │ │ ├── Console.kt │ │ │ └── IO.kt │ │ │ ├── exercise08 │ │ │ ├── Console.kt │ │ │ └── IO.kt │ │ │ ├── exercise09 │ │ │ ├── Console.kt │ │ │ ├── IO.kt │ │ │ └── Main.kt │ │ │ ├── listing01 │ │ │ └── Output.kt │ │ │ ├── listing02 │ │ │ └── Input.kt │ │ │ ├── listing03 │ │ │ └── AbstractReader.kt │ │ │ ├── listing04 │ │ │ └── ConsoleReader.kt │ │ │ ├── listing05 │ │ │ └── TestReader.kt │ │ │ ├── listing06 │ │ │ └── FileReader.kt │ │ │ ├── listing07 │ │ │ └── ScriptReader.kt │ │ │ └── listing08 │ │ │ ├── Computer.kt │ │ │ ├── Console.kt │ │ │ ├── IO.kt │ │ │ └── Main.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── effects │ │ ├── exercise01 │ │ └── ListTest.kt │ │ └── exercise04 │ │ └── IOTest.kt ├── fpinkotlin-functions-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── functions │ │ │ ├── exercise01 │ │ │ └── Functions.kt │ │ │ ├── exercise02 │ │ │ └── Functions.kt │ │ │ ├── exercise03 │ │ │ └── Functions.kt │ │ │ ├── exercise04 │ │ │ └── Functions.kt │ │ │ ├── exercise05 │ │ │ └── Functions.kt │ │ │ ├── exercise06 │ │ │ └── Functions.kt │ │ │ ├── exercise07 │ │ │ └── Functions.kt │ │ │ ├── exercise08 │ │ │ └── Functions.kt │ │ │ ├── exercise09 │ │ │ └── Functions.kt │ │ │ ├── exercise10 │ │ │ └── Functions.kt │ │ │ └── exercise11 │ │ │ └── Functions.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── functions │ │ ├── exercise01 │ │ └── FunctionsTest.kt │ │ ├── exercise02 │ │ └── FunctionsTest.kt │ │ ├── exercise03 │ │ └── FunctionsTest.kt │ │ ├── exercise04 │ │ └── FunctionsTest.kt │ │ ├── exercise05 │ │ └── FunctionsTest.kt │ │ ├── exercise06 │ │ └── FunctionsTest.kt │ │ ├── exercise07 │ │ └── FunctionsTest.kt │ │ ├── exercise08 │ │ └── FunctionsTest.kt │ │ ├── exercise09 │ │ └── FunctionsTest.kt │ │ ├── exercise10 │ │ └── FunctionsTest.kt │ │ └── exercise11 │ │ └── FunctionsTest.kt ├── fpinkotlin-functions-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── functions │ │ │ ├── exercise01 │ │ │ └── Functions.kt │ │ │ ├── exercise02 │ │ │ └── Functions.kt │ │ │ ├── exercise03 │ │ │ └── Functions.kt │ │ │ ├── exercise04 │ │ │ └── Functions.kt │ │ │ ├── exercise05 │ │ │ └── Functions.kt │ │ │ ├── exercise06 │ │ │ └── Functions.kt │ │ │ ├── exercise07 │ │ │ └── Functions.kt │ │ │ ├── exercise08 │ │ │ └── Functions.kt │ │ │ ├── exercise09 │ │ │ └── Functions.kt │ │ │ ├── exercise10 │ │ │ └── Functions.kt │ │ │ ├── exercise11 │ │ │ └── Functions.kt │ │ │ ├── exercise12 │ │ │ └── Functions.kt │ │ │ ├── listing01 │ │ │ └── FunFunctions.kt │ │ │ ├── listing02 │ │ │ └── Store.kt │ │ │ └── listing03 │ │ │ └── Store.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── functions │ │ ├── exercise01 │ │ └── FunctionsTest.kt │ │ ├── exercise02 │ │ └── FunctionsTest.kt │ │ ├── exercise03 │ │ └── FunctionsTest.kt │ │ ├── exercise04 │ │ └── FunctionsTest.kt │ │ ├── exercise05 │ │ └── FunctionsTest.kt │ │ ├── exercise06 │ │ └── FunctionsTest.kt │ │ ├── exercise07 │ │ └── FunctionsTest.kt │ │ ├── exercise08 │ │ └── FunctionsTest.kt │ │ ├── exercise09 │ │ └── FunctionsTest.kt │ │ ├── exercise10 │ │ └── FunctionsTest.kt │ │ └── exercise11 │ │ └── FunctionsTest.kt ├── fpinkotlin-handlingerrors-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── handlingerrors │ │ │ ├── exercise01 │ │ │ └── Either.kt │ │ │ ├── exercise02 │ │ │ └── Either.kt │ │ │ ├── exercise03 │ │ │ └── Either.kt │ │ │ ├── exercise04 │ │ │ └── Result.kt │ │ │ ├── exercise05 │ │ │ └── Result.kt │ │ │ ├── exercise06 │ │ │ └── Result.kt │ │ │ ├── exercise07 │ │ │ └── Result.kt │ │ │ ├── exercise08 │ │ │ └── Result.kt │ │ │ ├── exercise09 │ │ │ └── Result.kt │ │ │ ├── exercise10 │ │ │ └── Result.kt │ │ │ ├── exercise11 │ │ │ └── Result.kt │ │ │ ├── exercise12 │ │ │ └── Result.kt │ │ │ ├── exercise13 │ │ │ └── Result.kt │ │ │ └── exercise14 │ │ │ └── Result.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── handlingerrors │ │ ├── exercise01 │ │ └── EitherTest.kt │ │ ├── exercise02 │ │ └── EitherTest.kt │ │ ├── exercise03 │ │ └── EitherTest.kt │ │ ├── exercise04 │ │ └── ResultTest.kt │ │ ├── exercise05 │ │ └── ResultTest.kt │ │ ├── exercise06 │ │ └── ResultTest.kt │ │ ├── exercise07 │ │ └── ResultTest.kt │ │ ├── exercise08 │ │ └── ResultTest.kt │ │ ├── exercise09 │ │ └── ResultTest.kt │ │ ├── exercise10 │ │ └── ResultTest.kt │ │ ├── exercise11 │ │ └── ResultTest.kt │ │ ├── exercise12 │ │ └── ResultTest.kt │ │ ├── exercise13 │ │ └── ResultTest.kt │ │ └── exercise14 │ │ └── ResultTest.kt ├── fpinkotlin-handlingerrors-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── handlingerrors │ │ │ ├── exercise01 │ │ │ └── Either.kt │ │ │ ├── exercise02 │ │ │ └── Either.kt │ │ │ ├── exercise03 │ │ │ └── Either.kt │ │ │ ├── exercise04 │ │ │ └── Result.kt │ │ │ ├── exercise05 │ │ │ └── Result.kt │ │ │ ├── exercise06 │ │ │ └── Result.kt │ │ │ ├── exercise07 │ │ │ └── Result.kt │ │ │ ├── exercise08 │ │ │ └── Result.kt │ │ │ ├── exercise09 │ │ │ └── Result.kt │ │ │ ├── exercise10 │ │ │ └── Result.kt │ │ │ ├── exercise11 │ │ │ └── Result.kt │ │ │ ├── exercise12 │ │ │ └── Result.kt │ │ │ ├── exercise13 │ │ │ └── Result.kt │ │ │ ├── exercise14 │ │ │ └── Result.kt │ │ │ ├── listing01 │ │ │ ├── Either.kt │ │ │ └── List.kt │ │ │ ├── listing02 │ │ │ └── Result.kt │ │ │ ├── listing03 │ │ │ └── Toon.kt │ │ │ ├── listing04 │ │ │ └── Result.kt │ │ │ └── listing05 │ │ │ └── Toon.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── handlingerrors │ │ ├── exercise01 │ │ └── EitherTest.kt │ │ ├── exercise02 │ │ └── EitherTest.kt │ │ ├── exercise03 │ │ └── EitherTest.kt │ │ ├── exercise04 │ │ └── ResultTest.kt │ │ ├── exercise05 │ │ └── ResultTest.kt │ │ ├── exercise06 │ │ └── ResultTest.kt │ │ ├── exercise07 │ │ └── ResultTest.kt │ │ ├── exercise08 │ │ └── ResultTest.kt │ │ ├── exercise09 │ │ └── ResultTest.kt │ │ ├── exercise10 │ │ └── ResultTest.kt │ │ ├── exercise11 │ │ └── ResultTest.kt │ │ ├── exercise12 │ │ └── ResultTest.kt │ │ ├── exercise13 │ │ └── ResultTest.kt │ │ └── exercise14 │ │ └── ResultTest.kt ├── fpinkotlin-lists-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── lists │ │ │ ├── exercise01 │ │ │ └── List.kt │ │ │ ├── exercise02 │ │ │ └── List.kt │ │ │ ├── exercise03 │ │ │ └── List.kt │ │ │ ├── exercise04 │ │ │ └── List.kt │ │ │ ├── exercise05 │ │ │ └── List.kt │ │ │ ├── exercise06 │ │ │ └── List.kt │ │ │ ├── exercise07 │ │ │ └── List.kt │ │ │ ├── exercise08 │ │ │ └── List.kt │ │ │ ├── exercise09 │ │ │ └── List.kt │ │ │ ├── exercise10 │ │ │ └── List.kt │ │ │ ├── exercise11 │ │ │ └── List.kt │ │ │ ├── exercise12 │ │ │ └── List.kt │ │ │ ├── exercise13 │ │ │ └── List.kt │ │ │ ├── exercise14 │ │ │ └── List.kt │ │ │ ├── exercise15 │ │ │ └── List.kt │ │ │ ├── exercise16 │ │ │ └── List.kt │ │ │ ├── exercise17 │ │ │ └── List.kt │ │ │ ├── exercise18 │ │ │ └── List.kt │ │ │ ├── exercise19 │ │ │ └── List.kt │ │ │ ├── exercise20 │ │ │ └── List.kt │ │ │ └── exercise21 │ │ │ └── List.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── lists │ │ ├── exercise01 │ │ └── ListTest.kt │ │ ├── exercise02 │ │ └── ListTest.kt │ │ ├── exercise03 │ │ └── ListTest.kt │ │ ├── exercise04 │ │ └── ListTest.kt │ │ ├── exercise05 │ │ └── ListTest.kt │ │ ├── exercise06 │ │ └── ListTest.kt │ │ ├── exercise07 │ │ └── ListTest.kt │ │ ├── exercise08 │ │ └── ListTest.kt │ │ ├── exercise09 │ │ └── ListTest.kt │ │ ├── exercise10 │ │ └── ListTest.kt │ │ ├── exercise11 │ │ └── ListTest.kt │ │ ├── exercise12 │ │ └── ListTest.kt │ │ ├── exercise13 │ │ └── ListTest.kt │ │ ├── exercise14 │ │ └── ListTest.kt │ │ ├── exercise15 │ │ └── ListTest.kt │ │ ├── exercise16 │ │ └── ListTest.kt │ │ ├── exercise17 │ │ └── ListTest.kt │ │ ├── exercise18 │ │ └── ListTest.kt │ │ ├── exercise19 │ │ └── ListTest.kt │ │ ├── exercise20 │ │ └── ListTest.kt │ │ └── exercise21 │ │ └── ListTest.kt ├── fpinkotlin-lists-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── lists │ │ │ ├── exercise01 │ │ │ └── List.kt │ │ │ ├── exercise02 │ │ │ └── List.kt │ │ │ ├── exercise03 │ │ │ └── List.kt │ │ │ ├── exercise04 │ │ │ └── List.kt │ │ │ ├── exercise05 │ │ │ └── List.kt │ │ │ ├── exercise06 │ │ │ └── List.kt │ │ │ ├── exercise07 │ │ │ └── List.kt │ │ │ ├── exercise08 │ │ │ └── List.kt │ │ │ ├── exercise09 │ │ │ └── List.kt │ │ │ ├── exercise10 │ │ │ └── List.kt │ │ │ ├── exercise11 │ │ │ └── List.kt │ │ │ ├── exercise12 │ │ │ └── List.kt │ │ │ ├── exercise13 │ │ │ └── List.kt │ │ │ ├── exercise14 │ │ │ └── List.kt │ │ │ ├── exercise15 │ │ │ └── List.kt │ │ │ ├── exercise16 │ │ │ └── List.kt │ │ │ ├── exercise17 │ │ │ └── List.kt │ │ │ ├── exercise18 │ │ │ └── List.kt │ │ │ ├── exercise19 │ │ │ └── List.kt │ │ │ ├── exercise20 │ │ │ └── List.kt │ │ │ ├── exercise21 │ │ │ └── List.kt │ │ │ ├── listing01 │ │ │ └── List.kt │ │ │ └── listing02 │ │ │ └── List.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── lists │ │ ├── exercise01 │ │ └── ListTest.kt │ │ ├── exercise02 │ │ └── ListTest.kt │ │ ├── exercise03 │ │ └── ListTest.kt │ │ ├── exercise04 │ │ └── ListTest.kt │ │ ├── exercise05 │ │ └── ListTest.kt │ │ ├── exercise06 │ │ └── ListTest.kt │ │ ├── exercise07 │ │ └── ListTest.kt │ │ ├── exercise08 │ │ └── ListTest.kt │ │ ├── exercise09 │ │ └── ListTest.kt │ │ ├── exercise10 │ │ └── ListTest.kt │ │ ├── exercise11 │ │ └── ListTest.kt │ │ ├── exercise12 │ │ └── ListTest.kt │ │ ├── exercise13 │ │ └── ListTest.kt │ │ ├── exercise14 │ │ └── ListTest.kt │ │ ├── exercise15 │ │ └── ListTest.kt │ │ ├── exercise16 │ │ └── ListTest.kt │ │ ├── exercise17 │ │ └── ListTest.kt │ │ ├── exercise18 │ │ └── ListTest.kt │ │ ├── exercise19 │ │ └── ListTest.kt │ │ ├── exercise20 │ │ └── ListTest.kt │ │ ├── exercise21 │ │ └── ListTest.kt │ │ ├── listing01 │ │ └── ListTest.kt │ │ └── listing02 │ │ └── ListTest.kt ├── fpinkotlin-makingprogramssafer │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── makingprogramssafer │ │ │ ├── listing01 │ │ │ ├── CreditCard.kt │ │ │ ├── Donut.kt │ │ │ └── DonutShop.kt │ │ │ ├── listing02 │ │ │ ├── CreditCard.kt │ │ │ ├── Donut.kt │ │ │ ├── DonutShop.kt │ │ │ ├── Payment.kt │ │ │ └── Purchase.kt │ │ │ ├── listing03 │ │ │ ├── CreditCard.kt │ │ │ ├── Donut.kt │ │ │ ├── DonutShop.kt │ │ │ ├── Payment.kt │ │ │ └── Purchase.kt │ │ │ ├── listing04 │ │ │ ├── CreditCard.kt │ │ │ ├── Donut.kt │ │ │ ├── DonutShop.kt │ │ │ ├── Payment.kt │ │ │ └── Purchase.kt │ │ │ ├── listing05 │ │ │ ├── CreditCard.kt │ │ │ ├── Donut.kt │ │ │ ├── DonutShop.kt │ │ │ ├── Payment.kt │ │ │ └── Purchase.kt │ │ │ └── listing06 │ │ │ ├── CreditCard.kt │ │ │ ├── Donut.kt │ │ │ ├── DonutShop.kt │ │ │ ├── Payment.kt │ │ │ └── Purchase.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── makingprogramssafer │ │ ├── listing01 │ │ └── DonutShopTest.kt │ │ ├── listing02 │ │ └── DonutShopTest.kt │ │ ├── listing03 │ │ └── DonutShopTest.kt │ │ ├── listing04 │ │ └── DonutShopTest.kt │ │ ├── listing05 │ │ └── PaymentTest.kt │ │ └── listing06 │ │ └── PaymentTest.kt ├── fpinkotlin-optionaldata-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── optionaldata │ │ │ ├── exercise01 │ │ │ └── Option.kt │ │ │ ├── exercise02 │ │ │ └── Option.kt │ │ │ ├── exercise03 │ │ │ └── Option.kt │ │ │ ├── exercise04 │ │ │ └── Option.kt │ │ │ ├── exercise05 │ │ │ └── Option.kt │ │ │ ├── exercise06 │ │ │ └── Option.kt │ │ │ ├── exercise07 │ │ │ └── Option.kt │ │ │ ├── exercise08 │ │ │ └── Option.kt │ │ │ ├── exercise09 │ │ │ └── Option.kt │ │ │ ├── exercise10 │ │ │ └── Option.kt │ │ │ ├── exercise11 │ │ │ └── Option.kt │ │ │ └── exercise12 │ │ │ └── Option.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── optionaldata │ │ ├── exercise01 │ │ └── OptionTest.kt │ │ ├── exercise02 │ │ └── OptionTest.kt │ │ ├── exercise03 │ │ └── OptionTest.kt │ │ ├── exercise04 │ │ └── OptionTest.kt │ │ ├── exercise05 │ │ └── OptionTest.kt │ │ ├── exercise06 │ │ └── OptionTest.kt │ │ ├── exercise07 │ │ └── OptionTest.kt │ │ ├── exercise08 │ │ └── OptionTest.kt │ │ ├── exercise09 │ │ └── OptionTest.kt │ │ ├── exercise10 │ │ └── OptionTest.kt │ │ ├── exercise11 │ │ └── OptionTest.kt │ │ └── exercise12 │ │ └── OptionTest.kt ├── fpinkotlin-optionaldata-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── optionaldata │ │ │ ├── exercise01 │ │ │ └── Option.kt │ │ │ ├── exercise02 │ │ │ └── Option.kt │ │ │ ├── exercise03 │ │ │ └── Option.kt │ │ │ ├── exercise04 │ │ │ └── Option.kt │ │ │ ├── exercise05 │ │ │ └── Option.kt │ │ │ ├── exercise06 │ │ │ └── Option.kt │ │ │ ├── exercise07 │ │ │ └── Option.kt │ │ │ ├── exercise08 │ │ │ └── Option.kt │ │ │ ├── exercise09 │ │ │ └── Option.kt │ │ │ ├── exercise10 │ │ │ └── Option.kt │ │ │ ├── exercise11 │ │ │ └── Option.kt │ │ │ ├── exercise12 │ │ │ └── Option.kt │ │ │ ├── listing01 │ │ │ └── Option.kt │ │ │ ├── listing02 │ │ │ └── UseMap.kt │ │ │ └── listing03 │ │ │ └── UseMap.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── optionaldata │ │ ├── exercise01 │ │ └── OptionTest.kt │ │ ├── exercise02 │ │ └── OptionTest.kt │ │ ├── exercise03 │ │ └── OptionTest.kt │ │ ├── exercise04 │ │ └── OptionTest.kt │ │ ├── exercise05 │ │ └── OptionTest.kt │ │ ├── exercise06 │ │ └── OptionTest.kt │ │ ├── exercise07 │ │ └── OptionTest.kt │ │ ├── exercise08 │ │ └── OptionTest.kt │ │ ├── exercise09 │ │ └── OptionTest.kt │ │ ├── exercise10 │ │ └── OptionTest.kt │ │ ├── exercise11 │ │ └── OptionTest.kt │ │ └── exercise12 │ │ └── OptionTest.kt ├── fpinkotlin-recursion-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── recursion │ │ │ ├── exercise01 │ │ │ └── Add.kt │ │ │ ├── exercise02 │ │ │ └── Factorial.kt │ │ │ ├── exercise03 │ │ │ └── Fibonacci.kt │ │ │ ├── exercise04 │ │ │ ├── MakeString.kt │ │ │ └── String.kt │ │ │ ├── exercise05 │ │ │ └── FoldLeft.kt │ │ │ ├── exercise06 │ │ │ └── FoldRight.kt │ │ │ ├── exercise07 │ │ │ └── Reverse.kt │ │ │ ├── exercise08 │ │ │ └── Reverse.kt │ │ │ ├── exercise09 │ │ │ └── Range.kt │ │ │ ├── exercise10 │ │ │ └── Unfold.kt │ │ │ ├── exercise11 │ │ │ └── Range.kt │ │ │ ├── exercise12 │ │ │ └── Range.kt │ │ │ ├── exercise13 │ │ │ └── Unfold.kt │ │ │ ├── exercise14 │ │ │ └── Unfold.kt │ │ │ ├── exercise15 │ │ │ └── Fibonacci.kt │ │ │ ├── exercise16 │ │ │ └── Iterate.kt │ │ │ ├── exercise17 │ │ │ └── Map.kt │ │ │ └── exercise18 │ │ │ └── FiboCorecursive.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── recursion │ │ ├── exercise01 │ │ └── AddTest.kt │ │ ├── exercise02 │ │ └── FactorialTest.kt │ │ ├── exercise03 │ │ └── FibonacciTest.kt │ │ ├── exercise04 │ │ ├── MakeStringTest.kt │ │ └── StringTest.kt │ │ ├── exercise05 │ │ └── FoldTest.kt │ │ ├── exercise06 │ │ └── FoldRightTest.kt │ │ ├── exercise07 │ │ └── ReverseTest.kt │ │ ├── exercise08 │ │ └── ReverseTest.kt │ │ ├── exercise09 │ │ └── RangeTest.kt │ │ ├── exercise10 │ │ └── UnfoldTest.kt │ │ ├── exercise11 │ │ └── RangeTest.kt │ │ ├── exercise12 │ │ └── RangeTest.kt │ │ ├── exercise13 │ │ └── UnfoldTest.kt │ │ ├── exercise14 │ │ └── UnfoldTest.kt │ │ ├── exercise15 │ │ └── FibonacciTest.kt │ │ ├── exercise16 │ │ └── IterateTest.kt │ │ ├── exercise17 │ │ └── MapTest.kt │ │ └── exercise18 │ │ └── FiboCorecursiveTest.kt ├── fpinkotlin-recursion-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── recursion │ │ │ ├── exercise01 │ │ │ └── Add.kt │ │ │ ├── exercise02 │ │ │ └── Factorial.kt │ │ │ ├── exercise03 │ │ │ └── Fibonacci.kt │ │ │ ├── exercise04 │ │ │ ├── MakeString.kt │ │ │ └── String.kt │ │ │ ├── exercise05 │ │ │ └── FoldLeft.kt │ │ │ ├── exercise06 │ │ │ └── FoldRight.kt │ │ │ ├── exercise07 │ │ │ └── Reverse.kt │ │ │ ├── exercise08 │ │ │ └── Reverse.kt │ │ │ ├── exercise09 │ │ │ └── Range.kt │ │ │ ├── exercise10 │ │ │ └── Unfold.kt │ │ │ ├── exercise11 │ │ │ └── Range.kt │ │ │ ├── exercise12 │ │ │ └── Range.kt │ │ │ ├── exercise13 │ │ │ └── Unfold.kt │ │ │ ├── exercise14 │ │ │ └── Unfold.kt │ │ │ ├── exercise15 │ │ │ └── Fibonacci.kt │ │ │ ├── exercise16 │ │ │ └── Iterate.kt │ │ │ ├── exercise17 │ │ │ └── Map.kt │ │ │ ├── exercise18 │ │ │ └── FiboCorecursive.kt │ │ │ ├── listing01 │ │ │ └── MemoizedFibonacci.kt │ │ │ ├── listing02 │ │ │ └── Memoizer.kt │ │ │ ├── listing03 │ │ │ └── Memoizer.kt │ │ │ ├── listing04 │ │ │ └── Memoizer.kt │ │ │ └── listing05 │ │ │ └── Memoizer.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── recursion │ │ ├── exercise01 │ │ └── AddTest.kt │ │ ├── exercise02 │ │ └── FactorialTest.kt │ │ ├── exercise03 │ │ └── FibonacciTest.kt │ │ ├── exercise04 │ │ ├── MakeStringTest.kt │ │ └── StringTest.kt │ │ ├── exercise05 │ │ └── FoldTest.kt │ │ ├── exercise06 │ │ └── FoldRightTest.kt │ │ ├── exercise07 │ │ └── ReverseTest.kt │ │ ├── exercise08 │ │ └── ReverseTest.kt │ │ ├── exercise09 │ │ └── RangeTest.kt │ │ ├── exercise10 │ │ └── UnfoldTest.kt │ │ ├── exercise11 │ │ └── RangeTest.kt │ │ ├── exercise12 │ │ └── RangeTest.kt │ │ ├── exercise13 │ │ └── UnfoldTest.kt │ │ ├── exercise14 │ │ └── UnfoldTest.kt │ │ ├── exercise15 │ │ └── FibonacciTest.kt │ │ ├── exercise16 │ │ └── IterateTest.kt │ │ ├── exercise17 │ │ └── MapTest.kt │ │ ├── exercise18 │ │ └── FiboCorecursiveTest.kt │ │ ├── listing01 │ │ └── MemoizedFibonacciTest.kt │ │ └── listing02 │ │ └── MemoizerTest.kt ├── fpinkotlin-trees-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── trees │ │ │ ├── common │ │ │ └── Result.kt │ │ │ ├── exercise01 │ │ │ └── Tree.kt │ │ │ ├── exercise02 │ │ │ └── Tree.kt │ │ │ ├── exercise03 │ │ │ └── Tree.kt │ │ │ ├── exercise04 │ │ │ └── Tree.kt │ │ │ ├── exercise05 │ │ │ └── Tree.kt │ │ │ ├── exercise06 │ │ │ └── Tree.kt │ │ │ ├── exercise07 │ │ │ └── Tree.kt │ │ │ ├── exercise08 │ │ │ └── Tree.kt │ │ │ ├── exercise09 │ │ │ └── Tree.kt │ │ │ ├── exercise10 │ │ │ └── Tree.kt │ │ │ ├── exercise11 │ │ │ └── Tree.kt │ │ │ ├── exercise12 │ │ │ └── Tree.kt │ │ │ ├── exercise13 │ │ │ └── Tree.kt │ │ │ ├── exercise14 │ │ │ └── Tree.kt │ │ │ └── exercise15 │ │ │ └── Tree.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── trees │ │ ├── exercise01 │ │ └── TreeTest.kt │ │ ├── exercise02 │ │ └── TreeTest.kt │ │ ├── exercise03 │ │ └── TreeTest.kt │ │ ├── exercise04 │ │ └── TreeTest.kt │ │ ├── exercise05 │ │ └── TreeTest.kt │ │ ├── exercise06 │ │ └── TreeTest.kt │ │ ├── exercise07 │ │ └── TreeTest.kt │ │ ├── exercise08 │ │ └── TreeTest.kt │ │ ├── exercise09 │ │ └── TreeTest.kt │ │ ├── exercise10 │ │ └── TreeTest.kt │ │ ├── exercise11 │ │ └── TreeTest.kt │ │ ├── exercise12 │ │ └── TreeTest.kt │ │ ├── exercise13 │ │ └── TreeTest.kt │ │ ├── exercise14 │ │ └── TreeTest.kt │ │ └── exercise15 │ │ └── TreeTest.kt ├── fpinkotlin-trees-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── trees │ │ │ ├── common │ │ │ └── Result.kt │ │ │ ├── exercise01 │ │ │ └── Tree.kt │ │ │ ├── exercise02 │ │ │ └── Tree.kt │ │ │ ├── exercise03 │ │ │ └── Tree.kt │ │ │ ├── exercise04 │ │ │ └── Tree.kt │ │ │ ├── exercise05 │ │ │ └── Tree.kt │ │ │ ├── exercise06 │ │ │ └── Tree.kt │ │ │ ├── exercise07 │ │ │ └── Tree.kt │ │ │ ├── exercise08 │ │ │ └── Tree.kt │ │ │ ├── exercise09 │ │ │ └── Tree.kt │ │ │ ├── exercise10 │ │ │ └── Tree.kt │ │ │ ├── exercise11 │ │ │ └── Tree.kt │ │ │ ├── exercise12 │ │ │ └── Tree.kt │ │ │ ├── exercise13 │ │ │ └── Tree.kt │ │ │ ├── exercise14 │ │ │ └── Tree.kt │ │ │ ├── exercise15 │ │ │ └── Tree.kt │ │ │ └── listing01 │ │ │ └── Tree.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── trees │ │ ├── exercise01 │ │ └── TreeTest.kt │ │ ├── exercise02 │ │ └── TreeTest.kt │ │ ├── exercise03 │ │ └── TreeTest.kt │ │ ├── exercise04 │ │ └── TreeTest.kt │ │ ├── exercise05 │ │ └── TreeTest.kt │ │ ├── exercise06 │ │ └── TreeTest.kt │ │ ├── exercise07 │ │ └── TreeTest.kt │ │ ├── exercise08 │ │ └── TreeTest.kt │ │ ├── exercise09 │ │ └── TreeTest.kt │ │ ├── exercise10 │ │ └── TreeTest.kt │ │ ├── exercise11 │ │ └── TreeTest.kt │ │ ├── exercise12 │ │ └── TreeTest.kt │ │ ├── exercise13 │ │ └── TreeTest.kt │ │ ├── exercise14 │ │ └── TreeTest.kt │ │ └── exercise15 │ │ └── TreeTest.kt ├── fpinkotlin-workingwithlaziness-exercises │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── workingwithlaziness │ │ │ ├── exercise01 │ │ │ └── Lazy.kt │ │ │ ├── exercise02 │ │ │ └── Lazy.kt │ │ │ ├── exercise03 │ │ │ └── Lazy.kt │ │ │ ├── exercise04 │ │ │ └── Lazy.kt │ │ │ ├── exercise05 │ │ │ └── Lazy.kt │ │ │ ├── exercise06 │ │ │ └── Lazy.kt │ │ │ ├── exercise07 │ │ │ └── Lazy.kt │ │ │ ├── exercise08 │ │ │ └── Lazy.kt │ │ │ ├── exercise09 │ │ │ └── Lazy.kt │ │ │ ├── exercise10 │ │ │ └── Lazy.kt │ │ │ ├── exercise11 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise12 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise13 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise14 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise15 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise16 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise17 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise18 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise19 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise20 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise21 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise22 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise23 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise24 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise25 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise26 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise27 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise28 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise29 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise30 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ └── listing01 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── workingwithlaziness │ │ ├── exercise01 │ │ └── LazyTest.kt │ │ ├── exercise02 │ │ └── LazyTest.kt │ │ ├── exercise03 │ │ └── LazyTest.kt │ │ ├── exercise04 │ │ └── LazyTest.kt │ │ ├── exercise05 │ │ └── LazyTest.kt │ │ ├── exercise06 │ │ └── LazyTest.kt │ │ ├── exercise07 │ │ └── LazyTest.kt │ │ ├── exercise08 │ │ └── LazyTest.kt │ │ ├── exercise09 │ │ └── LazyTest.kt │ │ ├── exercise10 │ │ └── LazyTest.kt │ │ ├── exercise11 │ │ └── StreamTest.kt │ │ ├── exercise12 │ │ └── StreamTest.kt │ │ ├── exercise13 │ │ └── StreamTest.kt │ │ ├── exercise14 │ │ └── StreamTest.kt │ │ ├── exercise15 │ │ └── StreamTest.kt │ │ ├── exercise16 │ │ └── StreamTest.kt │ │ ├── exercise17 │ │ └── StreamTest.kt │ │ ├── exercise18 │ │ └── StreamTest.kt │ │ ├── exercise19 │ │ └── StreamTest.kt │ │ ├── exercise20 │ │ └── StreamTest.kt │ │ ├── exercise21 │ │ └── StreamTest.kt │ │ ├── exercise22 │ │ └── StreamTest.kt │ │ ├── exercise23 │ │ └── StreamTest.kt │ │ ├── exercise24 │ │ └── StreamTest.kt │ │ ├── exercise25 │ │ └── StreamTest.kt │ │ ├── exercise26 │ │ └── StreamTest.kt │ │ ├── exercise27 │ │ └── StreamTest.kt │ │ ├── exercise28 │ │ └── StreamTest.kt │ │ ├── exercise29 │ │ └── StreamTest.kt │ │ └── exercise30 │ │ └── StreamTest.kt ├── fpinkotlin-workingwithlaziness-solutions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── fpinkotlin │ │ │ └── workingwithlaziness │ │ │ ├── exercise01 │ │ │ └── Lazy.kt │ │ │ ├── exercise02 │ │ │ └── Lazy.kt │ │ │ ├── exercise03 │ │ │ └── Lazy.kt │ │ │ ├── exercise04 │ │ │ └── Lazy.kt │ │ │ ├── exercise05 │ │ │ └── Lazy.kt │ │ │ ├── exercise06 │ │ │ └── Lazy.kt │ │ │ ├── exercise07 │ │ │ └── Lazy.kt │ │ │ ├── exercise08 │ │ │ └── Lazy.kt │ │ │ ├── exercise09 │ │ │ └── Lazy.kt │ │ │ ├── exercise10 │ │ │ └── Lazy.kt │ │ │ ├── exercise11 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise12 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise13 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise14 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise15 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise16 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise17 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise18 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise19 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise20 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise21 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise22 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise23 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise24 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise25 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise26 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise27 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise28 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise29 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ ├── exercise30 │ │ │ ├── Lazy.kt │ │ │ └── Stream.kt │ │ │ └── listing01 │ │ │ ├── Lazy.kt │ │ │ ├── Stream.kt │ │ │ ├── TestSequence.kt │ │ │ └── TestStream.java │ │ └── test │ │ └── kotlin │ │ └── com │ │ └── fpinkotlin │ │ └── workingwithlaziness │ │ ├── exercise01 │ │ └── LazyTest.kt │ │ ├── exercise02 │ │ └── LazyTest.kt │ │ ├── exercise03 │ │ └── LazyTest.kt │ │ ├── exercise04 │ │ └── LazyTest.kt │ │ ├── exercise05 │ │ └── LazyTest.kt │ │ ├── exercise06 │ │ └── LazyTest.kt │ │ ├── exercise07 │ │ └── LazyTest.kt │ │ ├── exercise08 │ │ └── LazyTest.kt │ │ ├── exercise09 │ │ └── LazyTest.kt │ │ ├── exercise10 │ │ └── LazyTest.kt │ │ ├── exercise11 │ │ └── StreamTest.kt │ │ ├── exercise12 │ │ └── StreamTest.kt │ │ ├── exercise13 │ │ └── StreamTest.kt │ │ ├── exercise14 │ │ └── StreamTest.kt │ │ ├── exercise15 │ │ └── StreamTest.kt │ │ ├── exercise16 │ │ └── StreamTest.kt │ │ ├── exercise17 │ │ └── StreamTest.kt │ │ ├── exercise18 │ │ └── StreamTest.kt │ │ ├── exercise19 │ │ └── StreamTest.kt │ │ ├── exercise20 │ │ └── StreamTest.kt │ │ ├── exercise21 │ │ └── StreamTest.kt │ │ ├── exercise22 │ │ └── StreamTest.kt │ │ ├── exercise23 │ │ └── StreamTest.kt │ │ ├── exercise24 │ │ └── StreamTest.kt │ │ ├── exercise25 │ │ └── StreamTest.kt │ │ ├── exercise26 │ │ └── StreamTest.kt │ │ ├── exercise27 │ │ └── StreamTest.kt │ │ ├── exercise28 │ │ └── StreamTest.kt │ │ ├── exercise29 │ │ └── StreamTest.kt │ │ └── exercise30 │ │ └── StreamTest.kt ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts └── graphics ├── ImportProject.png ├── RunTest.png ├── RunTest1.png ├── failedTest01.png ├── failedTest02.png └── successTest03.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.war 8 | *.ear 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | 13 | # Others 14 | .DS_Store 15 | bin/ 16 | temp/ 17 | log/ 18 | distrib/ 19 | *.contrib 20 | *.keep 21 | *.zip 22 | *.*~ 23 | *.log 24 | *.iml 25 | .idea/ 26 | GeneratedCode/doc/api 27 | target/ 28 | src/site/doc/api 29 | .classpath 30 | .project 31 | .*/ 32 | .springBeans 33 | .checkstyle 34 | *-default.graphml 35 | *-default.html 36 | *-default.svg 37 | ivy-report.css 38 | *link to* 39 | .idea/ 40 | */build/ 41 | build/ 42 | *DS_Store 43 | pom.xml 44 | */pom.xml 45 | out/ 46 | */out/ 47 | LOG_FILE_IS_UNDEFINED 48 | .pmd 49 | *.ser 50 | *~ 51 | 52 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | sudo: required 4 | 5 | jdk: 6 | - openjdk8 7 | 8 | install: true 9 | 10 | script: 11 | - java -version 12 | - cd fpinkotlin-parent 13 | - ./gradlew assemble 14 | 15 | notifications: 16 | email: 17 | recipients: 18 | - fpinkotlin@volgadev.com 19 | on_success: always # default: change [always|never|change] 20 | on_failure: always # default: always [always|never|change] 21 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/build.gradle.kts: -------------------------------------------------------------------------------- 1 | ext["kotlintestVersion"] = "3.1.10" 2 | ext["logbackVersion"] = "1.2.3" 3 | ext["slf4jVersion"] = "1.7.25" 4 | 5 | plugins { 6 | base 7 | kotlin("jvm") version "1.3.10" //apply false 8 | } 9 | 10 | allprojects { 11 | 12 | group = "com.mydomain.mymultipleproject" 13 | 14 | version = "1.0-SNAPSHOT" 15 | 16 | repositories { 17 | jcenter() 18 | mavenCentral() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/client/build.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | plugins { 3 | application 4 | kotlin("jvm") 5 | } 6 | 7 | application { 8 | mainClassName = "com.mydomain.mymultipleproject.client.main.ClientKt" 9 | } 10 | 11 | dependencies { 12 | compile(kotlin("stdlib")) 13 | compile(project(":common")) 14 | } -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/client/src/main/kotlin/com/mydomain/mymultipleproject/client/main/Client.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.client.main 2 | 3 | import com.mydomain.mymultipleproject.common.MyJavaLibrary 4 | import com.mydomain.mymultipleproject.common.quadruple 5 | 6 | fun main(args: Array) { 7 | println("triple(4) = " + MyJavaLibrary.triple(4)) 8 | println("quadruple(3) = " + quadruple(3)) 9 | } -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | plugins { 3 | application 4 | kotlin("jvm") 5 | } 6 | 7 | dependencies { 8 | compile(kotlin("stdlib")) 9 | implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1") 10 | testCompile("io.kotlintest:kotlintest-runner-junit5:${project.rootProject.ext["kotlintestVersion"]}") 11 | testRuntime("org.slf4j:slf4j-nop:${project.rootProject.ext["slf4jVersion"]}") 12 | // testRuntime("ch.qos.logback:logback-classic:${project.rootProject.ext["logbackVersion"]}") 13 | } -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/java/com/mydomain/mymultipleproject/common/MyJavaLibrary.java: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common; 2 | 3 | public class MyJavaLibrary { 4 | 5 | public static int triple(int value) { 6 | return value * 3; 7 | } 8 | 9 | public static void main(String... args) { 10 | 11 | System.out.println(MyFileKt.isEven.invoke(2)); 12 | System.out.println(MyFileKt.isEven.invoke(3)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/MyKotlinLibrary.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common 2 | 3 | 4 | fun quadruple(value: Int) = value * 4 5 | 6 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example00/MyKotlinLibrary.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example00 2 | 3 | fun maxMultiple(multiple: Int, list: List): Int { 4 | var result = 0 5 | for (i in 1 until list.size) { 6 | if (list[i] / multiple * multiple == list[i] && list[i] > result) { 7 | result = list[i] 8 | } 9 | } 10 | return result 11 | } -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example01/MyKotlinLibrary.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example01 2 | 3 | fun isMaxMultiple(multiple: Int) = 4 | { max: Int, value: Int -> 5 | when { 6 | value / multiple * multiple == value && value > max -> value 7 | else -> max 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example02/MyKotlinLibrary.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example02 2 | 3 | fun isMaxMultiple(multiple: Int) = 4 | { max: Int, value: Int -> 5 | when { 6 | value / multiple * multiple == value && value > max -> value 7 | else -> max 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example03/SameLettersStrings.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example03 2 | 3 | fun main(args: Array) { 4 | val words = listOf("the", "act", "cat", "is", "bats", "tabs", "tac", "aabc", "abbc", "abca") 5 | 6 | val map = getCharUsed(words) 7 | 8 | println(map) 9 | } 10 | 11 | fun getCharUsed(words: List) = words.groupBy(::getCharMap) 12 | 13 | fun getCharMap(s: String): Map { 14 | val result = mutableMapOf() 15 | for (i in 0 until s.length) { 16 | val ch = s[i] 17 | if (result.containsKey(ch)) { 18 | result.replace(ch, result[ch]!! + 1) 19 | } else { 20 | result[ch] = 1 21 | } 22 | } 23 | return result 24 | } 25 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example04/SameLettersStrings.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example04 2 | 3 | fun main(args: Array) { 4 | val words = listOf("the", "act", "cat", "is", "bats", "tabs", "tac", "aabc", "abbc", "abca") 5 | 6 | val map = getCharUsed(words) 7 | 8 | println(map) 9 | } 10 | 11 | fun getCharUsed(words: List) = words.groupBy(::getCharMap) 12 | 13 | fun getCharMap(s: String): Map { 14 | val result = mutableMapOf() 15 | for (i in 0 until s.length) { 16 | val ch = s[i] 17 | if (result.containsKey(ch)) { 18 | result.replace(ch, result[ch]!! + 1) 19 | } else { 20 | result[ch] = 1 21 | } 22 | } 23 | return result 24 | } 25 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example05/SameLettersStrings.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example05 2 | 3 | fun main(args: Array) { 4 | val words = listOf("the", "act", "cat", "is", "bats", "tabs", "tac", "aabc", "abbc", "abca") 5 | 6 | val map = getCharUsed(words) 7 | 8 | println(map) 9 | } 10 | 11 | fun getCharUsed(words: List): Map, List> = words.groupBy(::getCharMap) 12 | 13 | fun getCharMap(s: String): Map = s.fold(mapOf(), ::updateMap) 14 | 15 | fun updateMap(map: Map, char: Char): Map = 16 | when { 17 | map.containsKey(char) -> map + Pair(char, map[char]!! + 1) 18 | else -> map + Pair(char, 1) 19 | } 20 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example06/SameLettersStrings.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example06 2 | 3 | fun main(args: Array) { 4 | val words = listOf("the", "act", "cat", "is", "bats", "tabs", "tac", "aabc", "abbc", "abca") 5 | 6 | val map = getCharUsed(words) 7 | 8 | println(map) 9 | } 10 | 11 | fun getCharUsed(words: List): Map, List> = words.groupBy(::getCharMap) 12 | 13 | fun getCharMap(s: String): Map = s.fold(mapOf(), ::updateMap) 14 | 15 | fun updateMap(map: Map, char: Char): Map = 16 | when { 17 | map.containsKey(char) -> map + Pair(char, map[char]!! + 1) 18 | else -> map + Pair(char, 1) 19 | } 20 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/main/kotlin/com/mydomain/mymultipleproject/common/example07/SameLettersStrings.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example07 2 | 3 | fun main(args: Array) { 4 | val words = listOf("the", "act", "cat", "is", "bats", "tabs", "tac", "aabc", "abbc", "abca") 5 | 6 | val map = getCharUsed(words) 7 | 8 | println(map) 9 | } 10 | 11 | fun getCharUsed(words: List): Map, List> = words.groupBy(::getCharMap) 12 | 13 | fun getCharMap(s: String): Map = s.fold(mapOf(), ::updateMap) 14 | 15 | fun updateMap(map: Map, char: Char): Map = 16 | when { 17 | map.containsKey(char) -> map + Pair(char, map[char]!! + 1) 18 | else -> map + Pair(char, 1) 19 | } 20 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/MyJavaLibraryTest.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common; 2 | 3 | import com.mydomain.mymultipleproject.common.MyJavaLibrary.triple 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class MyJavaLibraryTest : StringSpec() { 8 | 9 | init { 10 | "triple" { 11 | forAll(10000) { n: Int -> n + n + n == triple(n) } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example00/MyKotlinLibraryKtTest.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example00 2 | 3 | import io.kotlintest.shouldBe 4 | import io.kotlintest.specs.StringSpec 5 | 6 | internal class MyKotlinLibraryKtTest: StringSpec() { 7 | 8 | init { 9 | "maxMultiple" { 10 | val multiple = 2 11 | val list = listOf(4, 11, 8, 2, 3, 1, 14, 9, 5, 17, 6, 7) 12 | maxMultiple(multiple, list).shouldBe(14) 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example03/SameLettersStringKtTest.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example03 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class SameLettersStringKtTest: StringSpec() { 7 | 8 | init { 9 | "getCharUsed" { 10 | forAll(stringGenerator) { list: List>> -> 11 | getCharUsed(list.map { it.first }).keys.toSet() == list.asSequence().map { it.second }.toSet() 12 | } 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example04/ListGenerator.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example04 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.shrinking.ListShrinker 5 | import java.util.* 6 | 7 | 8 | class ListGenerator(private val gen: Gen, 9 | private val maxLength: Int) : Gen> { 10 | 11 | private val random = Random() 12 | 13 | override fun constants(): Iterable> = listOf(gen.constants().toList()) 14 | 15 | override fun random(): Sequence> = generateSequence { 16 | val size = random.nextInt(maxLength) 17 | gen.random().take(size).toList() 18 | } 19 | 20 | override fun shrinker() = ListShrinker() 21 | } 22 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example04/SameLettersStringKtTest.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example04 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class SameLettersStringKtTest: StringSpec() { 7 | 8 | init { 9 | "getCharUsed" { 10 | forAll(stringGenerator(100, 100)) { list: List>> -> 11 | getCharUsed(list.map { it.first }).keys.toSet() == list.asSequence().map { it.second }.toSet() 12 | } 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example05/ListGenerator.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example05 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.shrinking.ListShrinker 5 | import java.util.* 6 | 7 | 8 | class ListGenerator(private val gen: Gen, 9 | private val maxLength: Int) : Gen> { 10 | 11 | private val random = Random() 12 | 13 | override fun constants(): Iterable> = listOf(gen.constants().toList()) 14 | 15 | override fun random(): Sequence> = generateSequence { 16 | val size = random.nextInt(maxLength) 17 | gen.random().take(size).toList() 18 | } 19 | 20 | override fun shrinker() = ListShrinker() 21 | } 22 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example05/MapGenerator.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example05 2 | 3 | import io.kotlintest.properties.Gen 4 | 5 | fun mapGenerator(min: Char = 'a', max: Char = 'z'): Gen> = 6 | Gen.list(Gen.choose(min.toInt(), max.toInt()) 7 | .map(Int::toChar)).map(::makeMap) 8 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example05/SameLettersStringKtTest.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example05 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class SameLettersStringKtTest: StringSpec() { 7 | 8 | init { 9 | "getCharUsed" { 10 | forAll(stringGenerator(200, 50)) { list: List>> -> 11 | getCharUsed(list.map { it.first }).keys.toSet() == list.asSequence().map { it.second }.toSet() 12 | } 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example05/StringGenerator.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example05 2 | 3 | import io.kotlintest.properties.Gen 4 | 5 | 6 | fun stringGenerator(maxList: Int, 7 | maxString: Int): Gen>>> = 8 | ListGenerator(ListGenerator(Gen.choose(32, 127), maxString), maxList) 9 | .map { intListList -> 10 | intListList.asSequence().map { intList -> 11 | intList.map { n -> 12 | n.toChar() 13 | } 14 | }.map { charList -> 15 | Pair(String(charList.toCharArray()), makeMap(charList)) 16 | }.toList() 17 | } 18 | 19 | fun makeMap(charList: List): Map = charList.fold(mapOf(), ::updateMap) 20 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example06/ListGenerator.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example06 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.shrinking.ListShrinker 5 | import java.util.* 6 | 7 | 8 | class ListGenerator(private val gen: Gen, 9 | private val maxLength: Int) : Gen> { 10 | 11 | private val random = Random() 12 | 13 | override fun constants(): Iterable> = listOf(gen.constants().toList()) 14 | 15 | override fun random(): Sequence> = generateSequence { 16 | val size = random.nextInt(maxLength) 17 | gen.random().take(size).toList() 18 | } 19 | 20 | override fun shrinker() = ListShrinker() 21 | } 22 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example06/SameLettersStringKtTest.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example06 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class SameLettersStringKtTest: StringSpec() { 7 | 8 | init { 9 | "getCharUsed" { 10 | forAll(stringGenerator(200, 50)) { list: List>> -> 11 | getCharUsed(list.map { it.first }).keys.toSet() == list.asSequence().map { it.second }.toSet() 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example06/StringGenerator.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example06 2 | 3 | import io.kotlintest.properties.Gen 4 | 5 | 6 | fun stringGenerator(maxList: Int, 7 | maxString: Int): Gen>>> = 8 | ListGenerator(ListGenerator(Gen.choose(32, 127), maxString), maxList) 9 | .map { intListList -> 10 | intListList.asSequence().map { intList -> 11 | intList.map { n -> 12 | n.toChar() 13 | } 14 | }.map { charList -> 15 | Pair(String(charList.toCharArray()), makeMap(charList)) 16 | }.toList() 17 | } 18 | 19 | fun makeMap(charList: List): Map = charList.fold(mapOf(), ::updateMap) 20 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/common/src/test/kotlin/com/mydomain/mymultipleproject/common/example06/UpdateMapTest.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.common.example06 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class UpdateMapTest: StringSpec() { 7 | 8 | init { 9 | "getCharUsed" { 10 | forAll(MapGenerator, 11 | charGenerator(Char::isLetterOrDigit)) { map: Map, char -> 12 | updateMap(map, char)[char] == map.getOrDefault(char, 0) + 1 13 | && updateMap(map, char) - char == map - char 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/server/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | application 3 | kotlin("jvm") 4 | } 5 | 6 | application { 7 | mainClassName = "com.mydomain.mymultipleproject.server.main.Server" 8 | } 9 | 10 | dependencies { 11 | compile(kotlin("stdlib")) 12 | compile(project(":common")) 13 | } -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/server/src/main/java/com/mydomain/mymultipleproject/server/main/Server.java: -------------------------------------------------------------------------------- 1 | package com.mydomain.mymultipleproject.server.main; 2 | 3 | import com.mydomain.mymultipleproject.common.MyJavaLibrary; 4 | import com.mydomain.mymultipleproject.common.MyKotlinLibraryKt; 5 | 6 | public class Server { 7 | 8 | public static void main(String... args) { 9 | System.out.println("triple(4) = " + MyJavaLibrary.triple(4)); 10 | System.out.println("quadruple(3) = " + MyKotlinLibraryKt.quadruple(3)); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/kotlingradle/MyMultipleProject/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | include("server", "client", "common") 2 | -------------------------------------------------------------------------------- /examples/kotlingradle/MySimpleProject/build.gradle.kts: -------------------------------------------------------------------------------- 1 | val kotlintestVersion = "3.1.10" 2 | val logbackVersion = "1.2.3" 3 | val slf4jVersion = "1.7.25" 4 | 5 | plugins { 6 | application 7 | kotlin("jvm") version "1.2.71" 8 | } 9 | 10 | application { 11 | mainClassName = "com.mydomain.mysimpleproject.MainKt" 12 | } 13 | 14 | repositories { 15 | jcenter() 16 | } 17 | 18 | dependencies { 19 | compile(kotlin("stdlib")) 20 | testCompile("io.kotlintest:kotlintest-runner-junit5:$kotlintestVersion") 21 | testRuntime("org.slf4j:slf4j-nop:$slf4jVersion") 22 | } 23 | -------------------------------------------------------------------------------- /examples/kotlingradle/MySimpleProject/src/main/java/com/mydomain/mysimpleproject/MyClass.java: -------------------------------------------------------------------------------- 1 | package com.mydomain.mysimpleproject; 2 | 3 | public class MyClass { 4 | 5 | public static String getMessage(Lang language) { 6 | switch (language) { 7 | case ENGLISH: 8 | return "Hello"; 9 | case FRENCH: 10 | return "Bonjour"; 11 | case GERMAN: 12 | return "Hallo"; 13 | case SPANISH: 14 | return "Hola"; 15 | default: 16 | return "Saluton"; 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/kotlingradle/MySimpleProject/src/main/kotlin/com/mydomain/mysimpleproject/Main.kt: -------------------------------------------------------------------------------- 1 | package com.mydomain.mysimpleproject 2 | 3 | fun main(args: Array) { 4 | println(MyClass.getMessage(Lang.GERMAN)) 5 | } 6 | 7 | enum class Lang { GERMAN, FRENCH, ENGLISH, SPANISH } 8 | -------------------------------------------------------------------------------- /examples/kotlingradle/README.md: -------------------------------------------------------------------------------- 1 | ## The Joy of Kotlin 2 | 3 | This project holds the code example for appendix A and B of the book [The Joy of Kotlin](https://www.manning.com/books/the-joy-of-kotlin) 4 | 5 | It contains an example of a Gradle single module mixed Kotlin/Java project and an example of a multimodule mixed Kotlin/Java project. 6 | 7 | The multimodule project also contains all examples from Appendix B. 8 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-actors/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | compile("org.jetbrains.kotlinx:kotlinx-coroutines-core:${project.rootProject.ext["kotlinCoroutinesVersion"]}") 9 | testCompile(project(":fpinkotlin-common-test")) 10 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-exercises/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise01/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise01 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | 9 | class ListTest: StringSpec() { 10 | 11 | init { 12 | 13 | "length" { 14 | forAll(Gen.list(Gen.choose(1, 1_000))) { list -> 15 | List(*(list.toTypedArray())).lengthMemoized() == list.size 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-exercises/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise02/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise02 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | 9 | class ListTest: StringSpec() { 10 | 11 | init { 12 | 13 | "headSafe" { 14 | forAll(Gen.list(Gen.choose(1, 1_000))) { list -> 15 | List(*(list.toTypedArray())).headSafe().getOrElse(0) == if (list.isNotEmpty()) list[0] else 0 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-exercises/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise03/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise03 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ListTest: StringSpec() { 9 | 10 | init { 11 | 12 | "headSafe" { 13 | forAll(Gen.list(Gen.choose(1, 1_000))) { list -> 14 | List(*(list.toTypedArray())).lastSafe().getOrElse(0) == if (list.isNotEmpty()) list[list.size - 1] else 0 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-exercises/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise04/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise04 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | 9 | class ListTest: StringSpec() { 10 | 11 | init { 12 | 13 | "headSafe" { 14 | forAll(Gen.list(Gen.choose(1, 1_000))) { list -> 15 | List(*(list.toTypedArray())).headSafe().getOrElse(0) == if (list.isNotEmpty()) list[0] else 0 16 | } 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-exercises/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise19/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise19 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ListTest: StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(Gen.choose(0, 100)) { number -> 14 | range(0, number).foldLeft(0) { a -> { b -> a + b }} == (0 until number).sum() 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-solutions/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise02/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise02 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | 9 | class ListTest: StringSpec() { 10 | 11 | init { 12 | 13 | "headSafe" { 14 | forAll(Gen.list(Gen.choose(1, 1_000))) { list -> 15 | List(*(list.toTypedArray())).headSafe().getOrElse(0) == if (list.isNotEmpty()) list[0] else 0 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-solutions/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise03/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise03 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | 9 | class ListTest: StringSpec() { 10 | 11 | init { 12 | 13 | "headSafe" { 14 | forAll(Gen.list(Gen.choose(1, 1_000))) { list -> 15 | List(*(list.toTypedArray())).lastSafe().getOrElse(0) == if (list.isNotEmpty()) list[list.size - 1] else 0 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-solutions/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise04/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise04 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | 9 | class ListTest: StringSpec() { 10 | 11 | init { 12 | 13 | "headSafe" { 14 | forAll(Gen.list(Gen.choose(1, 1_000))) { list -> 15 | List(*(list.toTypedArray())).headSafe().getOrElse(0) == if (list.isNotEmpty()) list[0] else 0 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedlisthandling-solutions/src/test/kotlin/com/fpinkotlin/advancedlisthandling/exercise19/ListTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedlisthandling.exercise19 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ListTest: StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(Gen.choose(0, 100)) { number -> 14 | range(0, number).foldLeft(0) { a -> { b -> a + b }} == (0 until number).sum() 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedtrees-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedtrees-exercises/src/main/kotlin/com/fpinkotlin/advancedtrees/exercise02/MapEntry.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedtrees.exercise02 2 | 3 | class MapEntry, V> -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedtrees-exercises/src/test/kotlin/com/fpinkotlin/advancedtrees/exercise05/HeapTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedtrees.exercise05 2 | 3 | 4 | import com.fpinkotlin.common.List 5 | import io.kotlintest.shouldBe 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class HeapTest: StringSpec() { 9 | 10 | init { 11 | 12 | "plus" { 13 | val list = List(1, 2, 3, 4, 5, 6, 7) 14 | val queue: Heap = list.foldLeft(Heap()) { h -> { h + it } } 15 | queue.head.map { a -> a == 1 }.getOrElse(false) shouldBe true 16 | } 17 | 18 | "plus2" { 19 | val list = List(7, 3, 1, 6, 4, 6, 2) 20 | val queue: Heap = list.foldLeft(Heap()) { h -> { h + it } } 21 | queue.head.map { a -> a == 1 }.getOrElse(false) shouldBe true 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedtrees-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedtrees-solutions/src/main/kotlin/com/fpinkotlin/advancedtrees/listing02/Map.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedtrees.listing02 2 | 3 | import com.fpinkotlin.advancedtrees.common.Result 4 | 5 | class Map, V> { 6 | 7 | operator fun plus(entry: Pair<@UnsafeVariance K, V>): Map = TODO() 8 | 9 | operator fun minus(key: @UnsafeVariance K): Map = TODO() 10 | 11 | fun contains(key: @UnsafeVariance K): Boolean = TODO() 12 | 13 | fun get(key: @UnsafeVariance K): Result> = TODO() 14 | 15 | fun isEmpty(): Boolean = TODO() 16 | 17 | companion object { 18 | operator fun invoke(): Map = Map() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-advancedtrees-solutions/src/test/kotlin/com/fpinkotlin/advancedtrees/exercise05/HeapTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.advancedtrees.exercise05 2 | 3 | 4 | import com.fpinkotlin.common.List 5 | import io.kotlintest.shouldBe 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class HeapTest: StringSpec() { 9 | 10 | init { 11 | 12 | "plus" { 13 | val list = List(1, 2, 3, 4, 5, 6, 7) 14 | val queue: Heap = list.foldLeft(Heap()) { h -> { h + it } } 15 | queue.head.map { a -> a == 1 }.getOrElse(false) shouldBe true 16 | } 17 | 18 | "plus2" { 19 | val list = List(7, 3, 1, 6, 4, 6, 2) 20 | val queue: Heap = list.foldLeft(Heap()) { h -> { h + it } } 21 | queue.head.map { a -> a == 1 }.getOrElse(false) shouldBe true 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-common-test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | compile("io.kotlintest:kotlintest-runner-junit5:${project.rootProject.ext["kotlintestJunitVersion"]}") 9 | compile("io.kotlintest:kotlintest-extensions:${project.rootProject.ext["kotlintestJunitVersion"]}") 10 | runtime("org.slf4j:slf4j-nop:${project.rootProject.ext["slf4jVersion"]}") 11 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | plugins { 3 | kotlin("jvm") 4 | } 5 | 6 | dependencies { 7 | compile(kotlin("stdlib")) 8 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | compile("org.jdom:jdom2:2.0.6") 9 | testCompile(project(":fpinkotlin-common-test")) 10 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step1/empty.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step1/empty.xml -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step1/file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Paul 5 | Smith 6 | paul.smith@acme.com 7 | 100000 8 | 9 | 10 | Mary 11 | Colson 12 | mary.colson@acme.com 13 | 200000 14 | 15 | 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step2/file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Paul 5 | Smith 6 | paul.smith@acme.com 7 | 100000 8 | 9 | 10 | Mary 11 | Colson 12 | mary.colson@acme.com 13 | 200000 14 | 15 | 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step3/file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Paul 5 | Smith 6 | paul.smith@acme.com 7 | 100000 8 | 9 | 10 | Mary 11 | Colson 12 | mary.colson@acme.com 13 | 200000 14 | 15 | 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step4/file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Paul 5 | Smith 6 | paul.smith@acme.com 7 | 100000 8 | 9 | 10 | Mary 11 | Colson 12 | mary.colson@acme.com 13 | 200000 14 | 15 | 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step5/file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Paul 5 | Smith 6 | paul.smith@acme.com 7 | 100000 8 | 9 | 10 | Mary 11 | Colson 12 | mary.colson@acme.com 13 | 200000 14 | 15 | 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step6/file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Paul 5 | Smith 6 | paul.smith@acme.com 7 | 100000 8 | 9 | 10 | Mary 11 | Colson 12 | mary.colson@acme.com 13 | 200000 14 | 15 | 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/kotlin/com/fpinkotlin/commonproblems/xml/step7/file.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Paul 5 | Smith 6 | paul.smith@acme.com 7 | 100000 8 | 9 | 10 | Mary 11 | Colson 12 | mary.colson@acme.com 13 | 200000 14 | 15 | 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-commonproblems/src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | host=acme.org 2 | port=6666 3 | name= 4 | temp=71.3 5 | price=$45 6 | list=34,56,67,89 7 | person=id:3;firstName:Jeanne;lastName:Doe 8 | id=three 9 | type=SERIAL 10 | employees=\ 11 | id:3;firstName:Jane;lastName:Doe,\ 12 | id:5;firstName:Paul;lastName:Smith,\ 13 | id:8;firstName:Mary;lastName:Winston 14 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise02/ConsoleReader.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | import java.io.BufferedReader 6 | import java.io.InputStreamReader 7 | 8 | class ConsoleReader(reader: BufferedReader): AbstractReader(reader) { 9 | 10 | override fun readString(message: String): Result> { 11 | print("$message ") 12 | return readString() 13 | } 14 | 15 | override fun readInt(message: String): Result> { 16 | print("$message ") 17 | return readInt() 18 | } 19 | 20 | companion object { 21 | operator fun invoke(): ConsoleReader = 22 | ConsoleReader(BufferedReader(InputStreamReader(System.`in`))) 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise02/Input.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | 6 | interface Input: AutoCloseable { 7 | 8 | fun readString(): Result> 9 | 10 | fun readInt(): Result> 11 | 12 | fun readString(message: String): Result> = readString() 13 | 14 | fun readInt(message: String): Result> = readInt() 15 | } 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise02/Main.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.List 4 | 5 | 6 | fun readPersonsFromConsole(): List = TODO("readPersonsFromConsole") 7 | 8 | fun main(args: Array) { 9 | readPersonsFromConsole().forEach(::println) 10 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise02/Person.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | 6 | data class Person (val id: Int, val firstName: String, val lastName: String) 7 | 8 | fun person(input: Input): Result> = TODO("person") -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise03/FileReader.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise03 2 | 3 | import com.fpinkotlin.common.Result 4 | import java.io.BufferedReader 5 | 6 | 7 | class FileReader private constructor(private val reader: BufferedReader) : AbstractReader(reader), AutoCloseable { 8 | 9 | override fun close() = TODO("close") 10 | 11 | companion object { 12 | 13 | operator fun invoke(path: String): Result = TODO("invoke") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise03/Input.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise03 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | 6 | interface Input: AutoCloseable { 7 | 8 | fun readString(): Result> 9 | 10 | fun readInt(): Result> 11 | 12 | fun readString(message: String): Result> = readString() 13 | 14 | fun readInt(message: String): Result> = readInt() 15 | } 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise03/Person.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise03 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | 6 | data class Person (val id: Int, val firstName: String, val lastName: String) 7 | 8 | fun person(input: Input): Result> = input.readInt("Enter ID:") 9 | .flatMap { id -> 10 | id.second.readString("Enter first name:").flatMap { firstName -> 11 | firstName.second.readString("Enter last name:").map { lastName -> 12 | Pair(Person(id.first, firstName.first, lastName.first), lastName.second) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise03/data.txt: -------------------------------------------------------------------------------- 1 | 1 2 | Mickey 3 | Mouse 4 | 2 5 | Minnie 6 | Mouse 7 | 3 8 | Donald 9 | Duck 10 | 4 11 | Homer 12 | Simpson -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise05/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise05 2 | 3 | object Console { 4 | 5 | fun readln(): IO = TODO("readln") 6 | 7 | fun println(o: Any): IO = TODO("println") 8 | 9 | fun print(o: Any): IO = TODO("print") 10 | } 11 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise05/IO.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise05 2 | 3 | 4 | class IO(private val f: () -> A) { 5 | 6 | operator fun invoke() = f() 7 | 8 | companion object { 9 | 10 | val empty: IO = IO { } 11 | 12 | operator fun invoke(a: A): IO = IO { a } 13 | } 14 | } 15 | 16 | fun main(args: Array) { 17 | Console.print("Enter your name: ")() 18 | Console.println("Hello, ${Console.readln()()}")() 19 | } 20 | 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise06/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise06 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise06/IO.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise06 2 | 3 | 4 | class IO(private val f: () -> A) { 5 | 6 | operator fun invoke() = f() 7 | 8 | fun map (g: (A) -> B): IO = TODO("map") 9 | 10 | companion object { 11 | 12 | val empty: IO = IO { } 13 | 14 | operator fun invoke(a: A): IO = IO { a } 15 | } 16 | } 17 | 18 | fun main(args: Array) { 19 | val script = sayHello() 20 | script() 21 | } 22 | 23 | private fun sayHello(): IO = Console.print("Enter your name: ") 24 | .map { Console.readln()() } 25 | .map { buildMessage(it) } 26 | .map { Console.println(it)() } 27 | 28 | private fun buildMessage(name: String): String = "Hello, $name!" 29 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise07/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise07 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise08/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise08 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise09/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise09 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-exercises/src/main/kotlin/com/fpinkotlin/effects/exercise09/Main.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise09 2 | 3 | import com.fpinkotlin.common.Lazy 4 | import com.fpinkotlin.effects.exercise09.IO.Companion.condition 5 | 6 | 7 | private val buildMessage = { name: String -> 8 | condition(name.isNotEmpty(), Lazy { 9 | IO("Hello, $name!").flatMap { Console.println(it) } 10 | }) 11 | } 12 | 13 | fun program(f: (String) -> IO, title: String): IO { 14 | return IO.sequence(Console.println(title), 15 | IO.doWhile(Console.readln(), f), 16 | Console.println("bye!") 17 | ) 18 | } 19 | 20 | fun main(args: Array) { 21 | 22 | val program = program(buildMessage, "Enter the names of the persons to welcome: ") 23 | program() 24 | } 25 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise02/ConsoleReader.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | import java.io.BufferedReader 6 | import java.io.InputStreamReader 7 | 8 | class ConsoleReader(reader: BufferedReader): AbstractReader(reader) { 9 | 10 | override fun readString(message: String): Result> { 11 | print("$message ") 12 | return readString() 13 | } 14 | 15 | override fun readInt(message: String): Result> { 16 | print("$message ") 17 | return readInt() 18 | } 19 | 20 | companion object { 21 | operator fun invoke(): ConsoleReader = 22 | ConsoleReader(BufferedReader(InputStreamReader(System.`in`))) 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise02/Input.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.Result 4 | import java.io.Closeable 5 | 6 | 7 | interface Input: Closeable { 8 | 9 | fun readString(): Result> 10 | 11 | fun readInt(): Result> 12 | 13 | fun readString(message: String): Result> = readString() 14 | 15 | fun readInt(message: String): Result> = readInt() 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise02/Main.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.List 4 | import com.fpinkotlin.common.Stream 5 | 6 | 7 | fun readPersonsFromConsole(): List = Stream.unfold(ConsoleReader(), ::person).toList() 8 | 9 | fun main(args: Array) { 10 | readPersonsFromConsole().forEach(::println) 11 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise02/Person.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise02 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | 6 | data class Person (val id: Int, val firstName: String, val lastName: String) 7 | 8 | fun person(input: Input): Result> = input.readInt("Enter ID:") 9 | .flatMap { id -> 10 | id.second.readString("Enter first name:").flatMap { firstName -> 11 | firstName.second.readString("Enter last name:").map { lastName -> 12 | Pair(Person(id.first, firstName.first, lastName.first), lastName.second) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise03/FileReader.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise03 2 | 3 | import com.fpinkotlin.common.Result 4 | import java.io.BufferedReader 5 | import java.io.File 6 | 7 | 8 | class FileReader private constructor(private val reader: BufferedReader) : AbstractReader(reader), AutoCloseable { 9 | 10 | override fun close() { 11 | reader.close() 12 | } 13 | 14 | companion object { 15 | 16 | operator fun invoke(path: String): Result = try { 17 | Result(FileReader(File(path).bufferedReader())) 18 | } catch (e: Exception) { 19 | Result.failure(e) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise03/Input.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise03 2 | 3 | import com.fpinkotlin.common.Result 4 | import java.io.Closeable 5 | 6 | 7 | interface Input: Closeable { 8 | 9 | fun readString(): Result> 10 | 11 | fun readInt(): Result> 12 | 13 | fun readString(message: String): Result> = readString() 14 | 15 | fun readInt(message: String): Result> = readInt() 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise03/Person.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise03 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | 6 | data class Person (val id: Int, val firstName: String, val lastName: String) 7 | 8 | fun person(input: Input): Result> = input.readInt("Enter ID:") 9 | .flatMap { id -> 10 | id.second.readString("Enter first name:").flatMap { firstName -> 11 | firstName.second.readString("Enter last name:").map { lastName -> 12 | Pair(Person(id.first, firstName.first, lastName.first), lastName.second) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise03/data.txt: -------------------------------------------------------------------------------- 1 | 1 2 | Mickey 3 | Mouse 4 | 2 5 | Minnie 6 | Mouse 7 | 3 8 | Donald 9 | Duck 10 | 4 11 | Homer 12 | Simpson -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise05/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise05 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise05/IO.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise05 2 | 3 | 4 | class IO(private val f: () -> A) { 5 | 6 | operator fun invoke() = f() 7 | 8 | companion object { 9 | 10 | val empty: IO = IO { } 11 | 12 | operator fun invoke(a: A): IO = IO { a } 13 | } 14 | } 15 | 16 | fun main(args: Array) { 17 | Console.print("Enter your name: ")() 18 | Console.println("Hello, ${Console.readln()()}")() 19 | } 20 | 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise06/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise06 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise06/IO.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise06 2 | 3 | 4 | class IO(private val f: () -> A) { 5 | 6 | operator fun invoke() = f() 7 | 8 | fun map (g: (A) -> B): IO = IO { 9 | g(this()) 10 | } 11 | 12 | companion object { 13 | 14 | val empty: IO = IO { } 15 | 16 | operator fun invoke(a: A): IO = IO { a } 17 | } 18 | } 19 | 20 | fun main(args: Array) { 21 | val script = sayHello() 22 | script() 23 | } 24 | 25 | private fun sayHello(): IO = Console.print("Enter your name: ") 26 | .map { Console.readln()() } 27 | .map { buildMessage(it) } 28 | .map { Console.println(it)() } 29 | 30 | private fun buildMessage(name: String): String = "Hello, $name!" 31 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise07/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise07 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise08/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise08 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise09/Console.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise09 2 | 3 | import java.io.BufferedReader 4 | import java.io.IOException 5 | import java.io.InputStreamReader 6 | 7 | object Console { 8 | 9 | private val br = BufferedReader(InputStreamReader(System.`in`)) 10 | 11 | fun readln(): IO = IO { 12 | try { 13 | br.readLine() 14 | } catch (e: IOException) { 15 | throw IllegalStateException(e) 16 | } 17 | } 18 | 19 | fun println(o: Any): IO = IO { 20 | kotlin.io.println(o.toString()) 21 | } 22 | 23 | fun print(o: Any): IO = IO { 24 | kotlin.io.print(o.toString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/exercise09/Main.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.exercise09 2 | 3 | import com.fpinkotlin.common.Lazy 4 | 5 | 6 | private val buildMessage = { name: String -> 7 | IO.condition(name.isNotEmpty(), Lazy { 8 | IO("Hello, $name!").flatMap { Console.println(it) } 9 | }) 10 | } 11 | 12 | fun program(f: (String) -> IO, title: String): IO { 13 | return IO.sequence(Console.println(title), 14 | IO.doWhile(Console.readln(), f), 15 | Console.println("bye!") 16 | ) 17 | } 18 | 19 | fun main(args: Array) { 20 | 21 | val program = program(buildMessage, "Enter the names of the persons to welcome: ") 22 | program() 23 | } 24 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/listing02/Input.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.listing02 2 | 3 | import com.fpinkotlin.common.Result 4 | 5 | 6 | interface Input: AutoCloseable { 7 | 8 | fun readString(): Result> 9 | 10 | fun readInt(): Result> 11 | 12 | fun readString(message: String): Result> = readString() 13 | 14 | fun readInt(message: String): Result> = readInt() 15 | } 16 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/listing05/TestReader.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.listing05 2 | 3 | import com.fpinkotlin.effects.listing04.ConsoleReader 4 | 5 | fun main(args: Array) { 6 | 7 | val input = ConsoleReader() 8 | 9 | val rString = input.readString("Enter your name:").map { t -> t.first } 10 | 11 | val nameMessage = rString.map { "Hello, $it!" } 12 | 13 | nameMessage.forEach(::println, onFailure = { println(it.message)}) 14 | 15 | val rInt = input.readInt("Enter your age:").map { t -> t.first } 16 | 17 | val ageMessage = rInt.map { "You look younger than $it!" } 18 | 19 | ageMessage.forEach(::println, onFailure = { println("Invalid age. Please enter an integer")}) 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/listing06/FileReader.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.listing06 2 | 3 | import com.fpinkotlin.common.Result 4 | import com.fpinkotlin.effects.listing02.Input 5 | import com.fpinkotlin.effects.listing03.AbstractReader 6 | import java.io.BufferedReader 7 | import java.io.File 8 | 9 | 10 | class FileReader private constructor(reader: BufferedReader) : AbstractReader(reader) { 11 | 12 | companion object { 13 | 14 | operator fun invoke(path: String): Result = try { 15 | File(path).bufferedReader().use { Result(FileReader(it)) } 16 | } catch (e: Exception) { 17 | Result.failure(e) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-effects-solutions/src/main/kotlin/com/fpinkotlin/effects/listing08/Main.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.effects.listing08 2 | 3 | 4 | fun main(args: Array) { 5 | 6 | // IO.forever(Console.printLine("Hi..."))() 7 | 8 | /* 9 | val program = IO.forever(IO.unit("Hi again!") 10 | .flatMap { Console.printLine(it) } ) 11 | program() 12 | */ 13 | 14 | IO.repeat(100_000, Console.printLine("Hi..."))() 15 | 16 | // IO.doWhile(Console.printLine("Hi...")) { IO.unit(true) }() 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/main/kotlin/com/fpinkotlin/functions/exercise01/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise01 2 | 3 | fun square(n: Int) = n * n 4 | 5 | fun triple(n: Int) = n * 3 6 | 7 | fun compose(f: (Int) -> Int, g: (Int) -> Int): (Int) -> Int = TODO("compose") 8 | 9 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/main/kotlin/com/fpinkotlin/functions/exercise02/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise02 2 | 3 | 4 | fun square(n: Int) = n * n 5 | 6 | fun triple(n: Int) = n * 3 7 | 8 | // Define a generic compose. The exercise dos not consist in writing the implementation, but the signature. -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/main/kotlin/com/fpinkotlin/functions/exercise03/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise03 2 | 3 | 4 | class Compose 5 | 6 | fun square(n: Int) = n * n 7 | 8 | fun triple(n: Int) = n * 3 9 | 10 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 11 | 12 | val add: (Int) -> (Int) -> Int = TODO("add (in curried form)") 13 | 14 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/main/kotlin/com/fpinkotlin/functions/exercise04/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise04 2 | 3 | 4 | class Functions 5 | 6 | fun square(n: Int) = n * n 7 | 8 | fun triple(n: Int) = n * 3 9 | 10 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 11 | 12 | val add: (Int) -> (Int) -> Int = { a -> { b -> a + b} } 13 | 14 | val compose = null // Define a value function composing two (Int) -> Int functions -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/main/kotlin/com/fpinkotlin/functions/exercise05/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise05 2 | 3 | 4 | class Functions 5 | 6 | fun square(n: Int) = n * n 7 | 8 | fun triple(n: Int) = n * 3 9 | 10 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 11 | 12 | val add: (Int) -> (Int) -> Int = { a -> { b -> a + b} } 13 | 14 | val compose = { x: (Int) -> Int -> { y: (Int) -> Int -> { z: Int -> x(y(z)) } } } 15 | 16 | fun higherCompose() = null // Define a value function composing two (Int) -> Int functions 17 | 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/main/kotlin/com/fpinkotlin/functions/exercise06/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise06 2 | 3 | 4 | class Functions 5 | 6 | fun square(n: Int) = n * n 7 | 8 | fun triple(n: Int) = n * 3 9 | 10 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 11 | 12 | val add: (Int) -> (Int) -> Int = { a -> { b -> a + b} } 13 | 14 | val compose = { x: (Int) -> Int -> { y: (Int) -> Int -> { z: Int -> x(y(z)) } } } 15 | 16 | fun higherCompose(): ((U) -> V) -> ((T) -> U) -> (T) -> V = 17 | { f -> 18 | { g -> 19 | { x -> f(g(x)) } 20 | } 21 | } 22 | 23 | fun higherAndThen() = null // Define a value function composing two (Int) -> Int functions 24 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise01/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise01 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "compose" { 12 | forAll { x: Int -> 13 | compose(::square, ::triple)(x) == square(triple(x)) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise02/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise02 2 | 3 | 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class FunctionsTest: StringSpec() { 7 | 8 | init { 9 | // Uncomment after implementing the function 10 | // "compose" { 11 | // forAll { x: Int -> 12 | // compose(::square, ::triple)(x) == square(triple(x)) 13 | // } 14 | // } 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise03/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise03 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "add" { 12 | forAll { x: Int, y: Int -> 13 | add(x)(y) == x + y 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise04/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise04 2 | 3 | 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class FunctionsTest: StringSpec() { 7 | 8 | init { 9 | 10 | 11 | // Uncomment after implementing the function 12 | // "compose" { 13 | // forAll { x: Int -> 14 | // compose(::square)(::triple)(x) == square(triple(x)) 15 | // } 16 | // } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise05/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise05 2 | 3 | 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class FunctionsTest: StringSpec() { 7 | 8 | init { 9 | 10 | // Uncomment after implementing the function 11 | // "higherCompose" { 12 | // forAll { x: Int -> 13 | // higherCompose()(::square)(::triple)(x) == square(triple(x)) 14 | // } 15 | // } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise06/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise06 2 | 3 | 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class FunctionsTest: StringSpec() { 7 | 8 | init { 9 | 10 | 11 | // Uncomment after implementing the function 12 | // "higherAndThen" { 13 | // forAll { x: Int -> 14 | // higherAndThen()(::square)(::triple)(x) == triple(square(x)) 15 | // } 16 | // } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise07/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise07 2 | 3 | 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class FunctionsTest: StringSpec() { 7 | 8 | private val f = { a: Int -> { b: Double -> a * (1 + b / 100) } } 9 | 10 | init { 11 | 12 | // Uncomment after implementing the function 13 | // "partialA" { 14 | // forAll { x: Int, y: Double -> 15 | // y.isNaN() || y.isInfinite() || partialA(x, f)(y) == f(x)(y) 16 | // } 17 | // } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise08/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise08 2 | 3 | 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class FunctionsTest: StringSpec() { 7 | 8 | private val f = { a: Int -> { b: Double -> a * (1 + b / 100) } } 9 | 10 | init { 11 | 12 | // Uncomment after implementing the function 13 | // "partialB" { 14 | // forAll { x: Int, y: Double -> 15 | // y.isNaN() || y.isInfinite() || partialB(y, f)(x) == f(x)(y) 16 | // } 17 | // } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise09/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise09 2 | 3 | 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class FunctionsTest: StringSpec() { 7 | 8 | init { 9 | 10 | // Uncomment after implementing the function 11 | // "curried" { 12 | // forAll { a: Int, b: Double, c: String, d: Boolean -> 13 | // curried()(a)(b)(c)(d) == "$a, $b, $c, $d" 14 | // } 15 | // } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise10/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise10 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | private val f = { a: Int, b: Double -> a * (1 + b / 100) } 10 | 11 | init { 12 | 13 | "curry" { 14 | forAll { x: Int, y: Double -> 15 | y.isNaN() || y.isInfinite() || curry(f)(x)(y) == f(x, y) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-exercises/src/test/kotlin/com/fpinkotlin/functions/exercise11/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise11 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | private val f = { a: Int, b: Double -> a * (1 + b / 100) } 10 | 11 | init { 12 | 13 | "swapArgs" { 14 | forAll { x: Int, y: Double -> 15 | y.isNaN() || y.isInfinite() || swapArgs(curry(f))(y)(x) == f(x, y) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/main/kotlin/com/fpinkotlin/functions/exercise01/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise01 2 | 3 | 4 | fun square(n: Int) = n * n 5 | 6 | fun triple(n: Int) = n * 3 7 | 8 | fun compose(f: (Int) -> Int, g: (Int) -> Int): (Int) -> Int = { f(g(it)) } 9 | 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/main/kotlin/com/fpinkotlin/functions/exercise02/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise02 2 | 3 | 4 | fun square(n: Int) = n * n 5 | 6 | fun triple(n: Int) = n * 3 7 | 8 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 9 | 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/main/kotlin/com/fpinkotlin/functions/exercise03/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise03 2 | 3 | 4 | fun square(n: Int) = n * n 5 | 6 | fun triple(n: Int) = n * 3 7 | 8 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 9 | 10 | val add: (Int) -> (Int) -> Int = { a -> { b -> a + b} } 11 | 12 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/main/kotlin/com/fpinkotlin/functions/exercise04/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise04 2 | 3 | 4 | fun square(n: Int) = n * n 5 | 6 | fun triple(n: Int) = n * 3 7 | 8 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 9 | 10 | val add: (Int) -> (Int) -> Int = { a -> { b -> a + b} } 11 | 12 | val compose = { x: (Int) -> Int -> { y: (Int) -> Int -> { z: Int -> x(y(z)) } } } 13 | 14 | class Type 15 | 16 | class Type2 17 | 18 | val myList = Type() 19 | 20 | val myList2 = Type2() 21 | 22 | val myParentList: Type = myList 23 | 24 | val myParentList2: Type2 = myList2 -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/main/kotlin/com/fpinkotlin/functions/exercise06/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise06 2 | 3 | 4 | class Functions 5 | 6 | fun square(n: Int) = n * n 7 | 8 | fun triple(n: Int) = n * 3 9 | 10 | fun compose(f: (U) -> V, g: (T) -> U): (T) -> V = { f(g(it)) } 11 | 12 | val add: (Int) -> (Int) -> Int = { a -> { b -> a + b} } 13 | 14 | val compose = { x: (Int) -> Int -> { y: (Int) -> Int -> { z: Int -> x(y(z)) } } } 15 | 16 | fun higherCompose(): ((U) -> V) -> ((T) -> U) -> (T) -> V = 17 | { f -> 18 | { g -> 19 | { x -> f(g(x)) } 20 | } 21 | } 22 | 23 | fun higherAndThen(): ((T) -> U) -> ((U) -> V) -> (T) -> V = 24 | { f: (T) -> U -> 25 | { g: (U) -> V -> 26 | { x: T -> g(f(x)) } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise01/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise01 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "compose1" { 12 | forAll { x: Int -> 13 | compose(::square, ::triple)(x) == square(triple(x)) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise02/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise02 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "compose2" { 12 | forAll { x: Int -> 13 | compose(::square, ::triple)(x) == square(triple(x)) 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise03/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise03 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "add" { 12 | forAll { x: Int, y: Int -> 13 | add(x)(y) == x + y 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise04/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise04 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "compose4" { 12 | forAll { x: Int -> 13 | compose(::square)(::triple)(x) == square(triple(x)) 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise05/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise05 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "higherCompose" { 12 | forAll { x: Int -> 13 | higherCompose()(::square)(::triple)(x) == square(triple(x)) 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise06/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise06 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "higherAndThen" { 12 | forAll { x: Int -> 13 | higherAndThen()(::square)(::triple)(x) == triple(square(x)) 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise07/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise07 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | private val f = { a: Int -> { b: Double -> a * (1 + b / 100) } } 10 | 11 | init { 12 | 13 | "partialA" { 14 | forAll { x: Int, y: Double -> 15 | y.isNaN() || y.isInfinite() || partialA(x, f)(y) == f(x)(y) 16 | } 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise08/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise08 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | private val f = { a: Int -> { b: Double -> a * (1 + b / 100) } } 10 | 11 | init { 12 | 13 | "partialB" { 14 | forAll { x: Int, y: Double -> 15 | y.isNaN() || y.isInfinite() || partialB(y, f)(x) == f(x)(y) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise09/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise09 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | init { 10 | 11 | "curried" { 12 | forAll { a: Int, b: Double, c: String, d: Boolean -> 13 | curried()(a)(b)(c)(d) == "$a, $b, $c, $d" 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise10/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise10 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | private val f = { a: Int, b: Double -> a * (1 + b / 100) } 10 | 11 | init { 12 | 13 | "curry" { 14 | forAll { x: Int, y: Double -> 15 | y.isNaN() || y.isInfinite() || curry(f)(x)(y) == f(x, y) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-functions-solutions/src/test/kotlin/com/fpinkotlin/functions/exercise11/FunctionsTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.functions.exercise11 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FunctionsTest: StringSpec() { 8 | 9 | private val f = { a: Int, b: Double -> a * (1 + b / 100) } 10 | 11 | init { 12 | 13 | "swapArgs" { 14 | forAll { x: Int, y: Double -> 15 | y.isNaN() || y.isInfinite() || swapArgs(curry(f))(y)(x) == f(x, y) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-exercises/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise06/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise06 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | 7 | class ResultTest: StringSpec() { 8 | 9 | init { 10 | 11 | "exists" { 12 | forAll { z: Int -> 13 | Result(z).exists { it % 2 == 0 } == (z % 2 == 0) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-exercises/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise07/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise07 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class ResultTest: StringSpec() { 7 | 8 | init { 9 | 10 | "filter" { 11 | forAll { z: Int -> 12 | val errorMessage = "New error message" 13 | Result(z).filter { it % 2 == 0 }.mapFailure(errorMessage).toString() == when { 14 | z % 2 == 0 -> Result(z).toString() 15 | else -> Result.failure(errorMessage).toString() 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-exercises/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise09/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise09 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class ResultTest: StringSpec() { 8 | 9 | init { 10 | 11 | "forEach" { 12 | forAll { z: Int -> 13 | val errorMessage = "Value is odd" 14 | var result = false 15 | Result(if (z % 2 == 0) z else null, errorMessage).forEach { x -> result = (x == z)} 16 | result || z % 2 != 0 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-exercises/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise12/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise12 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class ResultTest: StringSpec() { 8 | 9 | init { 10 | 11 | "lift" { 12 | val f: (Int) -> Int = { if (it % 5 == 0) throw RuntimeException("Should not be seen") else it } 13 | forAll { z: Int -> 14 | lift(f)(Result(z)).toString() == 15 | if (z % 5 != 0) Result(f(z)).toString() 16 | else Result.failure("Should not be seen").toString() 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-exercises/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise14/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise14 2 | 3 | 4 | import com.fpinkotlin.handlingerrors.exercise14.Result.Companion.failure 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ResultTest: StringSpec() { 9 | 10 | init { 11 | 12 | "map2" { 13 | val p: (Int) -> (Int) -> Int = { a -> { b -> if (a > b) throw RuntimeException("a is too big") else b - a } } 14 | forAll { x: Int ,y: Int -> 15 | map2(Result(x), Result(y), p).toString() == 16 | if (x <= y) Result(p(x)(y)).toString() else failure("a is too big").toString() 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-solutions/src/main/kotlin/com/fpinkotlin/handlingerrors/listing01/Either.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.listing01 2 | 3 | sealed class Either { 4 | 5 | internal class Left(private val value: A): Either() { 6 | 7 | override fun toString(): String = "Left($value)" 8 | } 9 | 10 | internal class Right(private val value: B) : Either() { 11 | 12 | override fun toString(): String = "Right($value)" 13 | } 14 | 15 | companion object { 16 | 17 | fun left(value: A): Either = Left(value) 18 | 19 | fun right(value: B): Either = Right(value) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-solutions/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise06/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise06 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | 7 | class ResultTest: StringSpec() { 8 | 9 | init { 10 | 11 | "exists" { 12 | forAll { z: Int -> 13 | Result(z).exists { it % 2 == 0 } == (z % 2 == 0) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-solutions/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise07/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise07 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class ResultTest: StringSpec() { 7 | 8 | init { 9 | 10 | "filter" { 11 | forAll { z: Int -> 12 | val errorMessage = "New error message" 13 | Result(z).filter { it % 2 == 0 }.mapFailure(errorMessage).toString() == when { 14 | z % 2 == 0 -> Result(z).toString() 15 | else -> Result.failure(errorMessage).toString() 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-solutions/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise09/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise09 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class ResultTest: StringSpec() { 8 | 9 | init { 10 | 11 | "forEach" { 12 | forAll { z: Int -> 13 | val errorMessage = "Value is odd" 14 | var result = false 15 | Result(if (z % 2 == 0) z else null, errorMessage).forEach { x -> result = (x == z)} 16 | result || z % 2 != 0 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-solutions/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise12/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise12 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class ResultTest: StringSpec() { 8 | 9 | init { 10 | 11 | "lift" { 12 | val f: (Int) -> Int = { if (it % 5 == 0) throw RuntimeException("Should not be seen") else it } 13 | forAll { z: Int -> 14 | lift(f)(Result(z)).toString() == 15 | if (z % 5 != 0) Result(f(z)).toString() 16 | else Result.failure("Should not be seen").toString() 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-handlingerrors-solutions/src/test/kotlin/com/fpinkotlin/handlingerrors/exercise14/ResultTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.handlingerrors.exercise14 2 | 3 | 4 | import com.fpinkotlin.handlingerrors.exercise14.Result.Companion.failure 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ResultTest: StringSpec() { 9 | 10 | init { 11 | 12 | "map2" { 13 | val p: (Int) -> (Int) -> Int = { a -> { b -> if (a > b) throw RuntimeException("a is too big") else b - a } } 14 | forAll { x: Int ,y: Int -> 15 | map2(Result(x), Result(y), p).toString() == 16 | if (x <= y) Result(p(x)(y)).toString() else failure("a is too big").toString() 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-lists-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-lists-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") 5 | } 6 | 7 | dependencies { 8 | compile(kotlin("stdlib")) 9 | compile(project(":fpinkotlin-common")) 10 | compile(project(":fpinkotlin-common-test")) 11 | } 12 | val compileKotlin: KotlinCompile by tasks 13 | compileKotlin.kotlinOptions { 14 | freeCompilerArgs = listOf("-XXLanguage:+InlineClasses") 15 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing01/CreditCard.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing01 2 | 3 | class CreditCard { 4 | 5 | // total has a public getter (by default) and a private setter 6 | var total: Int = 0 7 | private set 8 | 9 | fun charge(price: Int) { 10 | this.total += price 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing01/Donut.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing01 2 | 3 | class Donut { 4 | companion object { 5 | val price = 2 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing01/DonutShop.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing01 2 | 3 | 4 | fun buyDonut(creditCard: CreditCard): Donut { 5 | val donut = Donut() 6 | creditCard.charge(Donut.price) 7 | return donut 8 | } 9 | 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing02/CreditCard.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing02 2 | 3 | class CreditCard { 4 | 5 | // total has a public getter (by default) and a private setter 6 | var total: Int = 0 7 | private set 8 | 9 | fun charge(price: Int) { 10 | this.total += price 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing02/Donut.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing02 2 | 3 | class Donut { 4 | companion object { 5 | val price = 2 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing02/DonutShop.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing02 2 | 3 | fun buyDonut(creditCard: CreditCard): Purchase = Purchase(Donut(), Payment(creditCard, Donut.price)) 4 | 5 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing02/Payment.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing02 2 | 3 | class Payment(val creditCard: CreditCard, val amount: Int) -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing02/Purchase.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing02 2 | 3 | class Purchase(val donut: Donut, val payment: Payment) 4 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing03/CreditCard.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing03 2 | 3 | class CreditCard { 4 | 5 | fun charge(price: Int) { 6 | // Charge the credit card 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing03/Donut.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing03 2 | 3 | class Donut { 4 | companion object { 5 | val price = 2 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing03/DonutShop.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing03 2 | 3 | fun buyDonut(creditCard: CreditCard): Purchase = Purchase(Donut(), Payment(creditCard, Donut.price)) 4 | 5 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing03/Payment.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing03 2 | 3 | class Payment(val creditCard: CreditCard, val amount: Int) -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing03/Purchase.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing03 2 | 3 | class Purchase(val donut: Donut, val payment: Payment) -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing04/CreditCard.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing04 2 | 3 | class CreditCard { 4 | 5 | fun charge(price: Int) { 6 | // Charge the credit card 7 | } 8 | 9 | } 10 | 11 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing04/Donut.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing04 2 | 3 | class Donut { 4 | companion object { 5 | val price = 2 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing04/DonutShop.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing04 2 | 3 | fun buyDonut(creditCard: CreditCard): Purchase = Purchase(Donut(), Payment(creditCard, Donut.price)) 4 | 5 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing04/Payment.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing04 2 | 3 | 4 | class Payment(val creditCard: CreditCard, val amount: Int) { 5 | 6 | fun combine(payment: Payment): Payment = 7 | if (creditCard == payment.creditCard) 8 | Payment(creditCard, amount + payment.amount) 9 | else 10 | throw IllegalStateException("Cards don't match.") 11 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing04/Purchase.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing04 2 | 3 | 4 | class Purchase(val donut: Donut, val payment: Payment) -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing05/CreditCard.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing05 2 | 3 | class CreditCard { 4 | 5 | fun charge(price: Int) { 6 | // Charge the credit card 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing05/Donut.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing05 2 | 3 | class Donut { 4 | companion object { 5 | val price = 2 6 | } 7 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing05/DonutShop.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing05 2 | 3 | fun buyDonuts(quantity: Int = 1, creditCard: CreditCard): Purchase = Purchase(List(quantity) { Donut() }, Payment(creditCard, Donut.price * quantity)) 4 | 5 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing05/Payment.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing05 2 | 3 | 4 | class Payment(val creditCard: CreditCard, val amount: Int) { 5 | 6 | fun combine(payment: Payment): Payment { 7 | if (creditCard == payment.creditCard) { 8 | return Payment(creditCard, amount + payment.amount) 9 | } else { 10 | throw IllegalStateException("Cards don't match.") 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing05/Purchase.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing05 2 | 3 | 4 | class Purchase(val donuts: List, val payment: Payment) -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing06/CreditCard.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing06 2 | 3 | class CreditCard { 4 | 5 | fun charge(price: Int) { 6 | // Charge the credit card 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing06/Donut.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing06 2 | 3 | class Donut { 4 | companion object { 5 | val price = 2 6 | } 7 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing06/DonutShop.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing06 2 | 3 | 4 | fun buyDonuts(quantity: Int = 1, creditCard: CreditCard): Purchase = 5 | Purchase(List(quantity) { Donut() }, Payment(creditCard, Donut.price * quantity)) 6 | 7 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing06/Payment.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing06 2 | 3 | 4 | data class Payment(val creditCard: CreditCard, val amount: Int) { 5 | fun combine(payment: Payment): Payment = 6 | if (creditCard == payment.creditCard) 7 | Payment(creditCard, amount + payment.amount) 8 | else 9 | throw IllegalStateException("Cards don't match.") 10 | 11 | companion object { 12 | fun groupByCard(payments: List): List = 13 | payments.groupBy { it.creditCard } 14 | .values 15 | .map { it.reduce(Payment::combine) } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/main/kotlin/com/fpinkotlin/makingprogramssafer/listing06/Purchase.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing06 2 | 3 | 4 | class Purchase(val donuts: List, val payment: Payment) -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-makingprogramssafer/src/test/kotlin/com/fpinkotlin/makingprogramssafer/listing01/DonutShopTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.makingprogramssafer.listing01 2 | 3 | import org.junit.jupiter.api.Assertions.assertEquals 4 | import org.junit.jupiter.api.Test 5 | 6 | 7 | class DonutShopTest { 8 | 9 | @Test 10 | fun testBuyCoffee() { 11 | val creditCard = CreditCard() 12 | buyDonut(creditCard) 13 | buyDonut(creditCard) 14 | assertEquals(Donut.price * 2, creditCard.total) 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise01/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise01 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | import java.util.* 7 | 8 | class OptionTest: StringSpec() { 9 | 10 | private val random = Random() 11 | 12 | init { 13 | 14 | "getOrElse" { 15 | val x = random.nextInt() 16 | val y: Int? = null 17 | forAll { z: Int -> 18 | Option(z).getOrElse(x) == z && Option(y).getOrElse(x) == x 19 | } 20 | } 21 | 22 | "getOrElse None" { 23 | val option: Option = Option.None 24 | option.getOrElse(1) shouldBe 1 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise02/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise02 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | import java.util.* 6 | 7 | class OptionTest: StringSpec() { 8 | 9 | private val random = Random() 10 | 11 | init { 12 | 13 | "getOrElse" { 14 | forAll { x: Int, z: Int -> 15 | Option(z).getOrElse { x } == z && Option(null as Int?).getOrElse { x } == x 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise03/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise03 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "map" { 11 | forAll { x: Int -> 12 | Option(x).map { it.toString() } == Option(x.toString()) 13 | } 14 | } 15 | 16 | "mapNone" { 17 | forAll { x: Int -> 18 | (Option(null).map { it * x }).isEmpty() 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise04/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise04 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "flatMap" { 11 | forAll { x: Int -> 12 | Option(x).flatMap { Option(it / 2) } == Option(x / 2) 13 | } 14 | } 15 | 16 | "flatMapNone" { 17 | forAll { x: Int -> 18 | (Option(null).flatMap { Option(it * x) }).isEmpty() 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise05/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise05 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | import java.util.* 7 | 8 | class OptionTest: StringSpec() { 9 | 10 | private val random = Random() 11 | 12 | init { 13 | 14 | "orElse" { 15 | val x: Option = Option(random.nextInt()) 16 | val y: Int? = null 17 | forAll(Gen.int()) { z -> 18 | Option(z).orElse { x } == Option(z) && Option(y).orElse { x } == x 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise06/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise06 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "filter" { 11 | val p: (Int) -> Boolean = { it % 5 != 0 } 12 | forAll { z: Int -> 13 | Option(z).filter(p) == if (p(z)) Option(z) else Option() 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise07/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise07 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "variance" { 11 | forAll { list: List -> 12 | variance(list) == when { 13 | list.isEmpty() -> Option() 14 | else -> Option((list.sum() / list.size).let { value -> 15 | list.map { x -> 16 | Math.pow((x - value), 2.0) 17 | }.let { it.sum() / it.size} }) 18 | } 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise08/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise08 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "lift" { 11 | val p: (Int) -> Boolean = { it % 5 != 0 } 12 | forAll { z: Int -> 13 | lift(p)(Option(z)) == Option(p(z)) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise09/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise09 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class OptionTest: StringSpec() { 8 | 9 | init { 10 | 11 | "lift" { 12 | val p: (Int) -> Int = { if (it % 5 == 0) throw RuntimeException("Should not be seen") else it } 13 | forAll(Gen.int()) { z -> 14 | lift(p)(Option(z)) == if (z % 5 != 0) Option(p(z)) else Option() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-exercises/src/test/kotlin/com/fpinkotlin/optionaldata/exercise10/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise10 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "map2" { 11 | val p: (Int) -> (Int) -> Int = { a -> { b -> a * b } } 12 | forAll { x: Int, y: Int -> 13 | map2(Option(x), Option(y), p) == Option(p(x)(y)) 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise01/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise01 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | import java.util.* 7 | 8 | class OptionTest: StringSpec() { 9 | 10 | private val random = Random() 11 | 12 | init { 13 | 14 | "getOrElse" { 15 | val x = random.nextInt() 16 | val y: Int? = null 17 | forAll { z: Int -> 18 | Option(z).getOrElse(x) == z && Option(y).getOrElse(x) == x 19 | } 20 | } 21 | 22 | "getOrElse None" { 23 | val option: Option = Option.None 24 | option.getOrElse(1) shouldBe 1 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise02/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise02 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | import java.util.* 6 | 7 | class OptionTest: StringSpec() { 8 | 9 | private val random = Random() 10 | 11 | init { 12 | 13 | "getOrElse" { 14 | forAll { x: Int, z: Int -> 15 | Option(z).getOrElse { x } == z && Option(null as Int?).getOrElse { x } == x 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise03/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise03 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "map" { 11 | forAll { x: Int -> 12 | Option(x).map { it.toString() } == Option(x.toString()) 13 | } 14 | } 15 | 16 | "mapNone" { 17 | forAll { x: Int -> 18 | (Option(null).map { it * x }).isEmpty() 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise04/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise04 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "flatMap" { 11 | forAll { x: Int -> 12 | Option(x).flatMap { Option(it / 2) } == Option(x / 2) 13 | } 14 | } 15 | 16 | "flatMapNone" { 17 | forAll { x: Int -> 18 | (Option(null).flatMap { Option(it * x) }).isEmpty() 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise05/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise05 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | import java.util.* 7 | 8 | class OptionTest: StringSpec() { 9 | 10 | private val random = Random() 11 | 12 | init { 13 | 14 | "orElse" { 15 | val x: Option = Option(random.nextInt()) 16 | val y: Int? = null 17 | forAll(Gen.int()) { z -> 18 | Option(z).orElse { x } == Option(z) && Option(y).orElse { x } == x 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise06/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise06 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "filter" { 11 | val p: (Int) -> Boolean = { it % 5 != 0 } 12 | forAll { z: Int -> 13 | Option(z).filter(p) == if (p(z)) Option(z) else Option() 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise07/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise07 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "variance" { 11 | forAll { list: List -> 12 | variance(list) == when { 13 | list.isEmpty() -> Option() 14 | else -> Option((list.sum() / list.size).let { value -> 15 | list.map { x -> 16 | Math.pow((x - value), 2.0) 17 | }.let { it.sum() / it.size} }) 18 | } 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise08/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise08 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "lift" { 11 | val p: (Int) -> Boolean = { it % 5 != 0 } 12 | forAll { z: Int -> 13 | lift(p)(Option(z)) == Option(p(z)) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise09/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise09 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class OptionTest: StringSpec() { 8 | 9 | init { 10 | 11 | "lift" { 12 | val p: (Int) -> Int = { if (it % 5 == 0) throw RuntimeException("Should not be seen") else it } 13 | forAll(Gen.int()) { z -> 14 | lift(p)(Option(z)) == if (z % 5 != 0) Option(p(z)) else Option() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-optionaldata-solutions/src/test/kotlin/com/fpinkotlin/optionaldata/exercise10/OptionTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.optionaldata.exercise10 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class OptionTest: StringSpec() { 7 | 8 | init { 9 | 10 | "map2" { 11 | val p: (Int) -> (Int) -> Int = { a -> { b -> a * b } } 12 | forAll { x: Int, y: Int -> 13 | map2(Option(x), Option(y), p) == Option(p(x)(y)) 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise01/Add.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise01 2 | 3 | 4 | fun add(a: Int, b: Int): Int = TODO("add") 5 | 6 | fun inc(n: Int) = n + 1 7 | fun dec(n: Int) = n - 1 8 | 9 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise02/Factorial.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise02 2 | 3 | object Factorial { 4 | val factorial: (Int)-> Int = TODO("factorial") 5 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise03/Fibonacci.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise03 2 | 3 | import java.math.BigInteger 4 | 5 | 6 | fun fib(x: Int): BigInteger = TODO("fibonacci") 7 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise04/MakeString.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise04 2 | 3 | fun makeString(list: List, delim: String): String { 4 | TODO("makeString") 5 | } 6 | 7 | fun List.head(): T = 8 | if (this.isEmpty()) 9 | throw IllegalArgumentException("head called on empty list") 10 | else 11 | this[0] 12 | 13 | fun List.tail(): List = 14 | if (this.isEmpty()) 15 | throw IllegalArgumentException("tail called on empty list") 16 | else 17 | this.subList(1, this.size) 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise04/String.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise04 2 | 3 | fun string(list: List): String = TODO("string") 4 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise05/FoldLeft.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise05 2 | 3 | fun List.head(): T = 4 | if (this.isEmpty()) 5 | throw IllegalArgumentException("head called on empty list") 6 | else 7 | this[0] 8 | 9 | fun List.tail(): List = 10 | if (this.isEmpty()) 11 | throw IllegalArgumentException("tail called on empty list") 12 | else 13 | this.subList(1, this.size) 14 | 15 | fun foldLeft(list: List, z: U, f: (U, T) -> U): U = TODO("foldLeft") 16 | 17 | fun sum(list: List): Int = TODO("sum") 18 | 19 | fun string(list: List): String = TODO("string") 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise06/FoldRight.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise06 2 | 3 | fun foldRight(list: List, identity: U, f: (T, U) -> U): U = TODO("foldRight") 4 | 5 | fun List.head(): T = 6 | if (this.isEmpty()) 7 | throw IllegalArgumentException("head called on empty list") 8 | else 9 | this[0] 10 | 11 | fun List.tail(): List = 12 | if (this.isEmpty()) 13 | throw IllegalArgumentException("tail called on empty list") 14 | else 15 | this.subList(1, this.size) 16 | 17 | fun sum(list: List): Int = foldRight(list, 0) { a, b -> a + b} 18 | 19 | fun string(list: List): String = foldRight(list, "") { a, b -> a + b} 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise09/Range.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise09 2 | 3 | 4 | fun range(start: Int, end: Int): List = TODO("range") -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise10/Unfold.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise10 2 | 3 | 4 | fun unfold(seed: T, f: (T) -> T, p: (T) -> Boolean): List = TODO("unfold") 5 | 6 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise11/Range.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise11 2 | 3 | 4 | fun unfold(seed: T, f: (T) -> T, p: (T) -> Boolean): List { 5 | val result: MutableList = mutableListOf() 6 | var elem = seed 7 | while (p(elem)) { 8 | result.add(elem) 9 | elem = f(elem) 10 | } 11 | return result 12 | } 13 | 14 | fun range(start: Int, end: Int): List = TODO("range") -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/main/kotlin/com/fpinkotlin/recursion/exercise16/Iterate.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise16 2 | 3 | 4 | fun iterate(seed: T, f: (T) -> T, n: Int): List = TODO("iterate") -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise01/AddTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise01 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class ListTest: StringSpec() { 7 | 8 | init { 9 | 10 | "add" { 11 | forAll { a: Int, b: Int -> 12 | a <= 0 || b <= 0 || add(a, b) == a + b 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise02/FactorialTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise02 2 | 3 | import com.fpinkotlin.recursion.exercise02.Factorial.factorial 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class FactorialTest: StringSpec() { 9 | 10 | init { 11 | 12 | "factorial" { 13 | forAll(Gen.choose(1, 30)) { n -> 14 | factorial(n + 1) == factorial(n) * (n + 1) 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise03/FibonacciTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise03 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FibonacciTest : StringSpec() { 8 | 9 | init { 10 | 11 | "fibonacci" { 12 | forAll(100, Gen.choose(3, 30_000)) { n -> 13 | fib(n) == fib(n - 1) + fib (n - 2) 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise04/MakeStringTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise04 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class MakeStringTest : StringSpec() { 8 | 9 | init { 10 | 11 | "makeString" { 12 | 13 | forAll(Gen.list(Gen.string())) { list -> 14 | makeString(list, ",") == list.joinToString(",") 15 | } 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise04/StringTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise04 2 | 3 | import com.fpinkotlin.generators.CharKListGenerator 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StringTest : StringSpec() { 8 | 9 | init { 10 | 11 | "string" { 12 | forAll(CharKListGenerator()) { list -> 13 | string(list) == list.toCharArray().fold("") { s, c -> s + c} 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise05/FoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise05 2 | 3 | import com.fpinkotlin.generators.CharKListGenerator 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FoldTest : StringSpec() { 8 | 9 | init { 10 | 11 | "string" { 12 | forAll(CharKListGenerator()) { list: List -> 13 | string(list) == list.toCharArray().fold("") { s, c -> s + c} 14 | } 15 | } 16 | } 17 | 18 | init { 19 | 20 | "sum" { 21 | forAll { list: List -> 22 | sum(list) == list.toIntArray().fold(0) { s, c -> s + c} 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise06/FoldRightTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise06 2 | 3 | import com.fpinkotlin.generators.CharKListGenerator 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FoldRightTest : StringSpec() { 8 | 9 | init { 10 | 11 | "string" { 12 | forAll(CharKListGenerator()) { list -> 13 | string(list) == list.toCharArray().fold("") { s, c -> s + c} 14 | } 15 | } 16 | } 17 | 18 | init { 19 | 20 | "sum" { 21 | forAll { list: List -> 22 | sum(list) == list.toIntArray().fold(0) { s, c -> s + c} 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise07/ReverseTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise07 2 | 3 | 4 | import com.fpinkotlin.recursion.exercise07.reverse 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ReverseTest : StringSpec() { 9 | 10 | init { 11 | 12 | "reverse" { 13 | forAll { list1: List, list2: List -> 14 | reverse(list1 + list2) == reverse(list2) + reverse(list1) 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise08/ReverseTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise08 2 | 3 | 4 | import com.fpinkotlin.recursion.exercise08.reverse 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ReverseTest : StringSpec() { 9 | 10 | init { 11 | 12 | "reverse" { 13 | forAll { list1: List, list2: List -> 14 | reverse(list1 + list2) == reverse(list2) + reverse(list1) 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise09/RangeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise09 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class RangeTest : StringSpec() { 9 | 10 | init { 11 | 12 | "range" { 13 | forAll(Gen.choose(0, 500), Gen.choose(0, 500)) { a: Int, b: Int -> 14 | range(a, a + b) == (a until a + b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise10/UnfoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise10 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class UnfoldTest : StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(Gen.choose(0, 10_000), Gen.choose(0, 10_000)) { a: Int, b: Int -> 14 | a > b || unfold(a, { x -> x + 1}) { x -> x < b } == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise11/RangeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise11 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class RangeTest : StringSpec() { 8 | 9 | init { 10 | 11 | "range" { 12 | forAll { a: Int, b: Int -> 13 | b > a || range(a, b) == (a until b).toList() 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise12/RangeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise12 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class RangeTest : StringSpec() { 8 | 9 | init { 10 | 11 | "range" { 12 | forAll { a: Int, b: Int -> 13 | b > a || range(a, b) == (a until b).toList() 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise13/UnfoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise13 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class UnfoldTest : StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(10, Gen.choose(0, 1_000), Gen.choose(0, 1_000)) { a: Int, b: Int -> 14 | a > b || unfold(a, { x -> x + 1}) { x -> x < b } == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise14/UnfoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise14 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class UnfoldTest : StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(Gen.choose(0, 10_000), Gen.choose(0, 10_000)) { a: Int, b: Int -> 14 | a > b || unfold(a, { x -> x + 1}) { x -> x < b } == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise15/FibonacciTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise15 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | 8 | class FibonacciTest : StringSpec() { 9 | 10 | init { 11 | 12 | "fibonacci" { 13 | forAll(100, Gen.choose(3, 300)) { n -> 14 | fibo(n - 1) == fibo(n).substringBeforeLast(",") 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise16/IterateTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise16 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class IterateTest : StringSpec() { 9 | 10 | init { 11 | 12 | "iterate" { 13 | forAll(Gen.choose(0, 1000), Gen.choose(0, 1000)) { a: Int, b: Int -> 14 | a > b || iterate(a, { x -> x + 1}, b - a) == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise17/MapTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise17 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class RangeTest : StringSpec() { 9 | 10 | init { 11 | 12 | "range" { 13 | forAll(Gen.choose(0, 1000), Gen.choose(0, 1000)) { a: Int, b: Int -> 14 | a > b || map((a until b).toList()) { it * 2} == (a * 2 until b * 2 step 2).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-exercises/src/test/kotlin/com/fpinkotlin/recursion/exercise18/FiboCorecursiveTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise18 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | 8 | class FiboCorecursiveTest : StringSpec() { 9 | 10 | init { 11 | 12 | "fibonacci" { 13 | forAll(100, Gen.choose(3, 300)) { n -> 14 | fiboCorecursive(n - 1) == fiboCorecursive(n).substringBeforeLast(",") 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise01/Add.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise01 2 | 3 | 4 | tailrec fun add(a: Int, b: Int): Int = if (b == 0) a else add(inc(a), dec(b)) 5 | 6 | fun add_(a: Int, b: Int): Int { 7 | var x = a 8 | var y = b 9 | while(y != 0) { 10 | x = inc(x) 11 | y = dec(y) 12 | } 13 | return x 14 | } 15 | 16 | fun inc(n: Int) = n + 1 17 | fun dec(n: Int) = n - 1 18 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise02/Factorial.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise02 2 | 3 | 4 | object Factorial { 5 | private lateinit var fact: (Int) -> Int 6 | init { 7 | fact = { n -> if (n <= 1) n else n * fact(n - 1) } 8 | } 9 | val factorial: (Int)-> Int = fact 10 | } 11 | 12 | object Factorial2 { 13 | val factorial2: (Int)-> Int by lazy { { n: Int -> if (n <= 1) n else n * factorial2(n - 1) } } 14 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise03/Fibonacci.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise03 2 | 3 | import java.math.BigInteger 4 | 5 | fun fibonacci(number: Int): Int = 6 | if (number == 0 || number == 1) 7 | 1 8 | else 9 | fibonacci(number - 1) + fibonacci(number - 2) 10 | 11 | 12 | fun fib(x: Int): BigInteger { 13 | tailrec 14 | fun fib(val1: BigInteger, val2: BigInteger, x: BigInteger): BigInteger = when { 15 | (x == BigInteger.ZERO) -> BigInteger.ONE 16 | (x == BigInteger.ONE) -> val1 + val2 17 | else -> fib(val2, val1 + val2, x - BigInteger.ONE) 18 | } 19 | return fib(BigInteger.ONE, BigInteger.ZERO, BigInteger.valueOf(x.toLong())) 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise04/String.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise04 2 | 3 | 4 | fun string(list: List): String { 5 | tailrec fun string(list: List, acc: String): String = 6 | if (list.isEmpty()) 7 | acc 8 | else 9 | string(list.tail(), acc + list.head()) 10 | return string(list, "") 11 | } 12 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise09/Range.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise09 2 | 3 | 4 | fun range(start: Int, end: Int): List { 5 | val result: MutableList = mutableListOf() 6 | var index = start 7 | while (index < end) { 8 | result.add(index) 9 | index++ 10 | } 11 | return result 12 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise10/Unfold.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise10 2 | 3 | 4 | fun unfold(seed: T, f: (T) -> T, p: (T) -> Boolean): List { 5 | val result: MutableList = mutableListOf() 6 | var elem = seed 7 | while (p(elem)) { 8 | result.add(elem) 9 | elem = f(elem) 10 | } 11 | return result 12 | } 13 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise11/Range.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise11 2 | 3 | 4 | fun unfold(seed: T, f: (T) -> T, p: (T) -> Boolean): List { 5 | val result: MutableList = mutableListOf() 6 | var elem = seed 7 | while (p(elem)) { 8 | result.add(elem) 9 | elem = f(elem) 10 | } 11 | return result 12 | } 13 | 14 | fun range(start: Int, end: Int): List = unfold(start, { it + 1 }, { it < end }) -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/exercise16/Iterate.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise16 2 | 3 | 4 | fun iterate(seed: T, f: (T) -> T, n: Int): List { 5 | tailrec fun iterate(acc: List, seed: T): List = 6 | if (acc.size < n) 7 | iterate(acc + seed, f(seed)) 8 | else 9 | acc 10 | return iterate(listOf(), seed) 11 | } 12 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/main/kotlin/com/fpinkotlin/recursion/listing02/Memoizer.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.listing02 2 | 3 | import java.util.concurrent.ConcurrentHashMap 4 | 5 | 6 | class Memoizer private constructor() { 7 | 8 | private val cache = ConcurrentHashMap() 9 | 10 | private fun doMemoize(function: (T) -> U): (T) -> U = 11 | { input -> 12 | cache.computeIfAbsent(input) { 13 | function(it) 14 | } 15 | } 16 | 17 | companion object { 18 | 19 | fun memoize(function: (T) -> U): (T) -> U = 20 | Memoizer().doMemoize(function) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise01/AddTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise01 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class ListTest: StringSpec() { 7 | 8 | init { 9 | 10 | "add" { 11 | forAll { a: Int, b: Int -> 12 | add(a, b) == a + b 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise02/FactorialTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise02 2 | 3 | import com.fpinkotlin.recursion.exercise02.Factorial.factorial 4 | import com.fpinkotlin.recursion.exercise02.Factorial2.factorial2 5 | import io.kotlintest.properties.Gen 6 | import io.kotlintest.properties.forAll 7 | import io.kotlintest.specs.StringSpec 8 | 9 | class FactorialTest: StringSpec() { 10 | 11 | init { 12 | 13 | "factorial" { 14 | forAll(Gen.choose(1, 30)) { n -> 15 | factorial(n + 1) == factorial(n) * (n + 1) 16 | } 17 | } 18 | "factorial2" { 19 | forAll(Gen.choose(1, 30)) { n -> 20 | factorial2(n + 1) == factorial2(n) * (n + 1) 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise03/FibonacciTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise03 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | import java.math.BigInteger 7 | 8 | infix operator fun BigInteger.plus(that: BigInteger): BigInteger = this.add(that) 9 | 10 | class FibonacciTest : StringSpec() { 11 | 12 | init { 13 | 14 | "fibonacci" { 15 | forAll(100, Gen.choose(3, 30_000)) { n -> 16 | fib(n) == fib(n - 1) + fib (n - 2) 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise04/MakeStringTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise04 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class MakeStringTest : StringSpec() { 8 | 9 | init { 10 | 11 | "makeString" { 12 | 13 | forAll(Gen.list(Gen.string())) { list -> 14 | makeString(list, ",") == list.joinToString(",") 15 | } 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise04/StringTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise04 2 | 3 | import com.fpinkotlin.generators.CharKListGenerator 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StringTest : StringSpec() { 8 | 9 | init { 10 | 11 | "string" { 12 | forAll(CharKListGenerator()) { list -> 13 | string(list) == list.toCharArray().fold("") { s, c -> s + c} 14 | } 15 | } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise05/FoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise05 2 | 3 | import com.fpinkotlin.generators.CharKListGenerator 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FoldTest : StringSpec() { 8 | 9 | init { 10 | 11 | "string" { 12 | forAll(CharKListGenerator()) { list: List -> 13 | string(list) == list.toCharArray().fold("") { s, c -> s + c} 14 | } 15 | } 16 | } 17 | 18 | init { 19 | 20 | "sum" { 21 | forAll { list: List -> 22 | sum(list) == list.toIntArray().fold(0) { s, c -> s + c} 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise06/FoldRightTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise06 2 | 3 | import com.fpinkotlin.generators.CharKListGenerator 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class FoldRightTest : StringSpec() { 8 | 9 | init { 10 | 11 | "string" { 12 | forAll(CharKListGenerator()) { list -> 13 | string(list) == list.toCharArray().fold("") { s, c -> s + c} 14 | } 15 | } 16 | } 17 | 18 | init { 19 | 20 | "sum" { 21 | forAll { list: List -> 22 | sum(list) == list.toIntArray().fold(0) { s, c -> s + c} 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise07/ReverseTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise07 2 | 3 | 4 | import com.fpinkotlin.recursion.exercise08.reverse 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ReverseTest : StringSpec() { 9 | 10 | init { 11 | 12 | "reverse" { 13 | forAll { list1: List, list2: List -> 14 | reverse(list1 + list2) == reverse(list2) + reverse(list1) 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise08/ReverseTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise08 2 | 3 | 4 | import com.fpinkotlin.recursion.exercise07.reverse 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class ReverseTest : StringSpec() { 9 | 10 | init { 11 | 12 | "reverse" { 13 | forAll { list1: List, list2: List -> 14 | reverse(list1 + list2) == reverse(list2) + reverse(list1) 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise09/RangeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise09 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class RangeTest : StringSpec() { 9 | 10 | init { 11 | 12 | "range" { 13 | forAll(Gen.choose(0, 500), Gen.choose(0, 500)) { a: Int, b: Int -> 14 | range(a, a + b) == (a until a + b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise10/UnfoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise10 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class UnfoldTest : StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(Gen.choose(0, 10_000), Gen.choose(0, 10_000)) { a: Int, b: Int -> 14 | a > b || unfold(a, { x -> x + 1}) { x -> x < b } == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise11/RangeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise11 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class RangeTest : StringSpec() { 8 | 9 | init { 10 | 11 | "range" { 12 | forAll { a: Int, b: Int -> 13 | b > a || range(a, b) == (a until b).toList() 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise12/RangeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise12 2 | 3 | 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class RangeTest : StringSpec() { 8 | 9 | init { 10 | 11 | "range" { 12 | forAll { a: Int, b: Int -> 13 | b > a || range(a, b) == (a until b).toList() 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise13/UnfoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise13 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class UnfoldTest : StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(10, Gen.choose(0, 1_000), Gen.choose(0, 1_000)) { a: Int, b: Int -> 14 | a > b || unfold(a, { x -> x + 1}) { x -> x < b } == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise14/UnfoldTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise14 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class UnfoldTest : StringSpec() { 9 | 10 | init { 11 | 12 | "unfold" { 13 | forAll(Gen.choose(0, 10_000), Gen.choose(0, 10_000)) { a: Int, b: Int -> 14 | a > b || unfold(a, { x -> x + 1}) { x -> x < b } == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise15/FibonacciTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise15 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | 8 | class FibonacciTest : StringSpec() { 9 | 10 | init { 11 | 12 | "fibonacci" { 13 | forAll(100, Gen.choose(3, 300)) { n -> 14 | fibo(n - 1) == fibo(n).substringBeforeLast(",") 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise16/IterateTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise16 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class IterateTest : StringSpec() { 9 | 10 | init { 11 | 12 | "iterate" { 13 | forAll(Gen.choose(0, 1000), Gen.choose(0, 1000)) { a: Int, b: Int -> 14 | a > b || iterate(a, { x -> x + 1}, b - a) == (a until b).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise17/MapTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise17 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class RangeTest : StringSpec() { 9 | 10 | init { 11 | 12 | "range" { 13 | forAll(Gen.choose(0, 1000), Gen.choose(0, 1000)) { a: Int, b: Int -> 14 | a > b || map((a until b).toList()) { it * 2} == (a * 2 until b * 2 step 2).toList() 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/exercise18/FiboCorecursiveTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.exercise18 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | 8 | class FiboCorecursiveTest : StringSpec() { 9 | 10 | init { 11 | 12 | "fibonacci" { 13 | forAll(100, Gen.choose(3, 300)) { n -> 14 | fiboCorecursive(n - 1) == fiboCorecursive(n).substringBeforeLast(",") 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/listing01/MemoizedFibonacciTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.listing01 2 | 3 | 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class MemoizedFibonacciTest : StringSpec() { 9 | 10 | init { 11 | 12 | "fibonacci" { 13 | forAll(100, Gen.choose(3, 300)) { n -> 14 | fibo(n - 1) == fibo(n).substringBeforeLast(",") 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-recursion-solutions/src/test/kotlin/com/fpinkotlin/recursion/listing02/MemoizerTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.recursion.listing02 2 | 3 | 4 | import com.fpinkotlin.recursion.exercise03.fib 5 | import io.kotlintest.properties.Gen 6 | import io.kotlintest.properties.forAll 7 | import io.kotlintest.specs.StringSpec 8 | 9 | 10 | class FiboCorecursiveTest : StringSpec() { 11 | 12 | init { 13 | 14 | "fibonacci" { 15 | forAll(100, Gen.choose(3, 300)) { n -> 16 | fib(n) == fib(n - 1) + fib (n - 2) 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise01/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise01 2 | 3 | import io.kotlintest.shouldBe 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class TreeTest: StringSpec() { 7 | 8 | init { 9 | 10 | "plus" { 11 | val tree = Tree() + 4 + 2 + 6 + 1 + 3 + 7 + 5 12 | tree.toString() shouldBe "(T (T (T E 1 E) 2 (T E 3 E)) 4 (T (T E 5 E) 6 (T E 7 E)))" 13 | } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise02/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise02 2 | 3 | import com.fpinkotlin.common.List 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "constructor List" { 12 | val tree = Tree(List(4, 2, 6, 1, 3, 7, 5)) 13 | tree.toString() shouldBe "(T (T (T E 1 E) 2 (T E 3 E)) 4 (T (T E 5 E) 6 (T E 7 E)))" 14 | } 15 | 16 | "constructor empty List" { 17 | val tree = Tree(List()) 18 | tree.toString() shouldBe "E" 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise03/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise03 2 | 3 | import com.fpinkotlin.common.List 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "contains" { 12 | val tree = Tree() + 4 + 2 + 6 + 1 + 3 + 7 + 5 13 | tree.contains(3) shouldBe true 14 | } 15 | 16 | "contains not" { 17 | val list: List = List() 18 | val tree = Tree(list) 19 | val result = tree.contains(8) 20 | result shouldBe false 21 | } 22 | 23 | "empty contains not" { 24 | val tree = Tree(List()) 25 | tree.contains(3) shouldBe false 26 | } 27 | } 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise07/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise07 2 | 3 | 4 | 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class TreeTest: StringSpec() { 9 | 10 | init { 11 | 12 | "merge" { 13 | forAll { list1: List, list2: List -> 14 | val tree1 = list1.fold(Tree()) { tree, elem -> tree + elem } 15 | val tree2 = list2.fold(Tree()) { tree, elem -> tree + elem } 16 | list1.asSequence().plus(list2).all { i: Int -> tree1.merge(tree2).contains(i) } 17 | } 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise08/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise08 2 | 3 | 4 | import com.fpinkotlin.generators.IntListGenerator 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class TreeTest: StringSpec() { 9 | 10 | init { 11 | 12 | "foldLeft" { 13 | forAll(IntListGenerator()) { (array, list) -> 14 | val tree = list.foldLeft(Tree()) { tree -> { elem -> tree + elem } } 15 | val f = { a: Int -> { b: Int -> a + b } } 16 | tree.foldLeft(0, f, f) == array.sum() 17 | } 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise11/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise11 2 | 3 | 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "testMap" { 12 | val tree = Tree(4, 2, 1, 3, 6, 5, 7) 13 | val result = tree.map { x -> x + 2 } 14 | result.toString() shouldBe "(T (T (T E 3 E) 4 (T E 5 E)) 6 (T (T E 7 E) 8 (T E 9 E)))" 15 | } 16 | 17 | "testMap2" { 18 | val tree = Tree(-4, 2, -1, 3, 6, -5, 7) 19 | val result = tree.map { x -> x * x } 20 | result.toString() shouldBe "(T (T (T E 1 E) 4 (T E 9 E)) 16 (T E 25 (T E 36 (T E 49 E))))" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise13/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise13 2 | 3 | 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "testToListInOrderRight" { 12 | val tree2 = Tree(4, 6, 7, 5, 2, 1, 3) 13 | tree2.toListInOrderRight().toString() shouldBe "[7, 6, 5, 4, 3, 2, 1, NIL]" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-exercises/src/test/kotlin/com/fpinkotlin/trees/exercise15/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise15 2 | 3 | 4 | import com.fpinkotlin.common.range 5 | import com.fpinkotlin.trees.exercise15.Tree.Companion.balance 6 | import io.kotlintest.shouldBe 7 | import io.kotlintest.specs.StringSpec 8 | 9 | class TreeTest: StringSpec() { 10 | 11 | 12 | init { 13 | "testPlus" { 14 | val limit = 100_000 15 | val orderedTestList = range(0, limit) 16 | val temp = orderedTestList.foldLeft(Tree()) { t -> { i -> t + i } } 17 | val tree = balance(temp) 18 | tree.size shouldBe limit 19 | (tree.height <= 2 * log2nlz(tree.size + 1)) shouldBe true 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise01/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise01 2 | 3 | import io.kotlintest.shouldBe 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class TreeTest: StringSpec() { 7 | 8 | init { 9 | 10 | "plus" { 11 | val tree = Tree() + 4 + 2 + 6 + 1 + 3 + 7 + 5 12 | tree.toString() shouldBe "(T (T (T E 1 E) 2 (T E 3 E)) 4 (T (T E 5 E) 6 (T E 7 E)))" 13 | } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise02/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise02 2 | 3 | import com.fpinkotlin.common.List 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "constructor List" { 12 | val tree = Tree(List(4, 2, 6, 1, 3, 7, 5)) 13 | tree.toString() shouldBe "(T (T (T E 1 E) 2 (T E 3 E)) 4 (T (T E 5 E) 6 (T E 7 E)))" 14 | } 15 | 16 | "constructor empty List" { 17 | val tree = Tree(List()) 18 | tree.toString() shouldBe "E" 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise03/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise03 2 | 3 | import com.fpinkotlin.common.List 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "contains" { 12 | val tree = Tree() + 4 + 2 + 6 + 1 + 3 + 7 + 5 13 | tree.contains(3) shouldBe true 14 | } 15 | 16 | "contains not" { 17 | val list: List = List() 18 | val tree = Tree(list) 19 | val result = tree.contains(8) 20 | result shouldBe false 21 | } 22 | 23 | "empty contains not" { 24 | val tree = Tree(List()) 25 | tree.contains(3) shouldBe false 26 | } 27 | } 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise07/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise07 2 | 3 | 4 | 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class TreeTest: StringSpec() { 9 | 10 | init { 11 | 12 | "merge" { 13 | forAll { list1: List, list2: List -> 14 | val tree1 = list1.fold(Tree()) { tree, elem -> tree + elem } 15 | val tree2 = list2.fold(Tree()) { tree, elem -> tree + elem } 16 | list1.asSequence().plus(list2).all { i: Int -> tree1.merge(tree2).contains(i) } 17 | } 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise08/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise08 2 | 3 | 4 | import com.fpinkotlin.generators.IntListGenerator 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class TreeTest: StringSpec() { 9 | 10 | init { 11 | 12 | "foldLeft" { 13 | forAll(IntListGenerator()) { (array, list) -> 14 | val tree = list.foldLeft(Tree()) { tree -> { elem -> tree + elem } } 15 | val f = { a: Int -> { b: Int -> a + b } } 16 | tree.foldLeft(0, f, f) == array.sum() 17 | } 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise11/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise11 2 | 3 | 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "testMap" { 12 | val tree = Tree(4, 2, 1, 3, 6, 5, 7) 13 | val result = tree.map { x -> x + 2 } 14 | result.toString() shouldBe "(T (T (T E 3 E) 4 (T E 5 E)) 6 (T (T E 7 E) 8 (T E 9 E)))" 15 | } 16 | 17 | "testMap2" { 18 | val tree = Tree(-4, 2, -1, 3, 6, -5, 7) 19 | val result = tree.map { x -> x * x } 20 | result.toString() shouldBe "(T (T (T E 1 E) 4 (T E 9 E)) 16 (T E 25 (T E 36 (T E 49 E))))" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise13/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise13 2 | 3 | 4 | import io.kotlintest.shouldBe 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class TreeTest: StringSpec() { 8 | 9 | init { 10 | 11 | "testToListInOrderRight" { 12 | val tree2 = Tree(4, 6, 7, 5, 2, 1, 3) 13 | tree2.toListInOrderRight().toString() shouldBe "[7, 6, 5, 4, 3, 2, 1, NIL]" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-trees-solutions/src/test/kotlin/com/fpinkotlin/trees/exercise15/TreeTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.trees.exercise15 2 | 3 | 4 | import com.fpinkotlin.common.range 5 | import com.fpinkotlin.trees.exercise15.Tree.Companion.balance 6 | import io.kotlintest.shouldBe 7 | import io.kotlintest.specs.StringSpec 8 | 9 | class TreeTest: StringSpec() { 10 | 11 | 12 | init { 13 | "testPlus" { 14 | val limit = 100_000 15 | val orderedTestList = range(0, limit) 16 | val temp = orderedTestList.foldLeft(Tree()) { t -> { i -> t + i } } 17 | val tree = balance(temp) 18 | tree.size shouldBe limit 19 | (tree.height <= 2 * log2nlz(tree.size + 1)) shouldBe true 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise01/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise01 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | // Add implementation 7 | 8 | override fun invoke(): A = TODO("not implemented") 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise02/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise02 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | } 10 | 11 | fun constructMessage(greetings: Lazy, name: Lazy): Lazy = TODO("Implement this function") 12 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise03/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise03 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | } 10 | 11 | 12 | val constructMessage: (Lazy) -> (Lazy) -> Lazy = TODO("Implement this function") 13 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise04/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise04 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | 10 | companion object { 11 | 12 | val lift2: ((String) -> (String) -> String) -> (Lazy) -> (Lazy) -> Lazy = 13 | TODO("lift2") 14 | } 15 | } 16 | 17 | val consMessage: (String) -> (String) -> String = 18 | { greetings -> 19 | { name -> 20 | "$greetings, $name!" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise05/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise05 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | } 10 | 11 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 12 | TODO("lift2") 13 | 14 | val consMessage: (String) -> (String) -> String = 15 | { greetings -> 16 | { name -> 17 | "$greetings, $name!" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise06/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise06 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | 10 | fun map(f: (A) -> B): Lazy = TODO("lift2") 11 | } 12 | 13 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 14 | { ls1 -> 15 | { ls2 -> 16 | Lazy { f(ls1())(ls2()) } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise07/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise07 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | 10 | fun map(f: (A) -> B): Lazy = Lazy { f(value) } 11 | 12 | fun flatMap(f: (A) -> Lazy): Lazy = TODO("flatMap") 13 | } 14 | 15 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 16 | { ls1 -> 17 | { ls2 -> 18 | Lazy { f(ls1())(ls2()) } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise08/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise08 2 | 3 | import com.fpinkotlin.common.List 4 | 5 | class Lazy(function: () -> A): () -> A { 6 | 7 | private val value: A by lazy(function) 8 | 9 | override operator fun invoke(): A = value 10 | 11 | fun map(f: (A) -> B): Lazy = Lazy { f(value) } 12 | 13 | fun flatMap(f: (A) -> Lazy): Lazy = Lazy { f(value)() } 14 | } 15 | 16 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 17 | { ls1 -> 18 | { ls2 -> 19 | Lazy { f(ls1())(ls2()) } 20 | } 21 | } 22 | 23 | 24 | fun sequence(lst: List>): Lazy> = TODO("sequence") 25 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise12/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise12 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class StreamTest: StringSpec() { 7 | 8 | init { 9 | 10 | "head&tail" { 11 | forAll { a: Int -> 12 | val stream = Stream.from(a) 13 | val first = stream.head().getOrElse(0) 14 | val second = stream.tail().getOrElse(Stream.invoke()).head().getOrElse(0) 15 | first == a && second == a + 1 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise13/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise13 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "dropAtMost&takeAtMost" { 12 | forAll(Gen.choose(0, 100_000), Gen.choose(0, 500)) { a, offset -> 13 | val stream = Stream.from(a).dropAtMost(offset).takeAtMost(offset) 14 | stream.isEmpty() || stream.head().map { it == a + offset }.getOrElse(false) 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise14/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise14 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "dropAtMost&takeAtMost" { 12 | forAll(Gen.choose(0, 100_000), Gen.choose(0, 500)) { a, offset -> 13 | val stream = Stream.from(a).dropAtMost(offset).takeAtMost(offset) 14 | stream.isEmpty() || stream.head().map { it == a + offset }.getOrElse(false) 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise15/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise15 2 | 3 | import com.fpinkotlin.common.range 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class StreamTest: StringSpec() { 9 | 10 | init { 11 | 12 | "toList" { 13 | forAll(10, Gen.choose(0, 1_000)) { a -> 14 | val list = range(0, a) 15 | val stream = Stream.from(0).takeAtMost(a) 16 | list.toString() == stream.toList().toString() 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise16/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise16 2 | 3 | import com.fpinkotlin.common.range 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class StreamTest: StringSpec() { 9 | 10 | init { 11 | 12 | "iterate" { 13 | forAll(10, Gen.choose(0, 1_000)) { a -> 14 | val list = range(0, a) 15 | val stream = Stream.iterate(0) { it + 1 }.takeAtMost(a) 16 | list.toString() == stream.toList().toString() 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise22/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise22 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "headSafeViaFoldRight" { 12 | forAll(Gen.choose(0, 100_000), Gen.choose(0, 500)) { a, offset -> 13 | val stream = Stream.from(a).dropAtMost(offset).takeAtMost(offset) 14 | stream.isEmpty() || stream.headSafeViaFoldRight().map { it == a + offset }.getOrElse(false) 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise26/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise26 2 | 3 | import com.fpinkotlin.common.range 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class StreamTest: StringSpec() { 9 | 10 | init { 11 | 12 | "flatMap" { 13 | forAll(10, Gen.choose(0, 1_000)) { a -> 14 | fun inc(i: Int) = i + 1 15 | val list = range(0, a) 16 | val stream = Stream.iterate(Lazy{ inc(-1) }, ::inc).takeWhileViaFoldRight { it < a }.flatMap { Stream.from(it).takeAtMost(1) } 17 | list.toString() == stream.toList().toString() 18 | } 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise27/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise27 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "find" { 12 | forAll(Gen.choose(0, 1_000)) { a -> 13 | val stream = Stream.from(0).takeAtMost(a) 14 | stream.find { it == a / 2 }.getOrElse(0) == a / 2 && 15 | stream.find { it == a * 2 }.getOrElse(-1) == -1 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise28/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise28 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "fibs" { 12 | forAll(Gen.choose(3, 50)) { a -> 13 | val stream = fibs() 14 | val r1 = stream.dropAtMost(a - 1).head() 15 | val r2 = stream.dropAtMost(a - 2).head() 16 | val r3 = stream.dropAtMost(a - 3).head() 17 | r1.flatMap { x -> r2.flatMap { y -> r3.map { z -> z + y == x } } }.getOrElse(false) 18 | } 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-exercises/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise29/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise29 2 | 3 | import com.fpinkotlin.common.Result 4 | import com.fpinkotlin.common.range 5 | import io.kotlintest.properties.Gen 6 | import io.kotlintest.properties.forAll 7 | import io.kotlintest.specs.StringSpec 8 | 9 | class StreamTest: StringSpec() { 10 | 11 | init { 12 | 13 | "unfold" { 14 | forAll(10, Gen.choose(0, 1_000)) { a -> 15 | val list = range(0, a) 16 | val stream = Stream.unfold(-1) { Result(Pair(it + 1, it + 1)) }.takeAtMost(a) 17 | list.toString() == stream.toList().toString() 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | } 4 | 5 | dependencies { 6 | compile(kotlin("stdlib")) 7 | compile(project(":fpinkotlin-common")) 8 | testCompile(project(":fpinkotlin-common-test")) 9 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise01/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise01 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | } 10 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise02/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise02 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | } 10 | 11 | fun constructMessage(greetings: Lazy, name: Lazy): Lazy = Lazy { "${greetings()}, ${name()}!" } 12 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise03/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise03 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | } 10 | 11 | val constructMessage: (Lazy) -> (Lazy) -> Lazy = 12 | { greetings -> 13 | { name -> 14 | Lazy { "${greetings()}, ${name()}!" } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise05/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise05 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | } 10 | 11 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 12 | { ls1 -> 13 | { ls2 -> 14 | Lazy { f(ls1())(ls2()) } 15 | } 16 | } 17 | 18 | val consMessage: (String) -> (String) -> String = 19 | { greetings -> 20 | { name -> 21 | "$greetings, $name!" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise06/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise06 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | 10 | fun map(f: (A) -> B): Lazy = Lazy{ f(value) } 11 | } 12 | 13 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 14 | { ls1 -> 15 | { ls2 -> 16 | Lazy { f(ls1())(ls2()) } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise07/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise07 2 | 3 | 4 | class Lazy(function: () -> A): () -> A { 5 | 6 | private val value: A by lazy(function) 7 | 8 | override operator fun invoke(): A = value 9 | 10 | fun map(f: (A) -> B): Lazy = Lazy { f(value) } 11 | 12 | fun flatMap(f: (A) -> Lazy): Lazy = Lazy { f(value)() } 13 | } 14 | 15 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 16 | { ls1 -> 17 | { ls2 -> 18 | Lazy { f(ls1())(ls2()) } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/exercise08/Lazy.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise08 2 | 3 | import com.fpinkotlin.common.List 4 | 5 | class Lazy(function: () -> A): () -> A { 6 | 7 | private val value: A by lazy(function) 8 | 9 | override operator fun invoke(): A = value 10 | 11 | fun map(f: (A) -> B): Lazy = Lazy { f(value) } 12 | 13 | fun flatMap(f: (A) -> Lazy): Lazy = Lazy { f(value)() } 14 | } 15 | 16 | fun lift2(f: (A) -> (B) -> C): (Lazy) -> (Lazy) -> Lazy = 17 | { ls1 -> 18 | { ls2 -> 19 | Lazy { f(ls1())(ls2()) } 20 | } 21 | } 22 | 23 | 24 | fun sequence(lst: List>): Lazy> = Lazy { lst.map { it() } } 25 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/listing01/TestSequence.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.listing01 2 | 3 | fun main(args: Array) { 4 | val sequence: Sequence = generateSequence(0, Int::inc) 5 | println(sequence.first()) 6 | println(sequence.drop(1).first()) 7 | println(sequence.drop(2).first()) 8 | println(sequence.first()) 9 | println(sequence.drop(1).first()) 10 | println(sequence.drop(2).first()) 11 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/main/kotlin/com/fpinkotlin/workingwithlaziness/listing01/TestStream.java: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.listing01; 2 | 3 | import java.util.stream.Stream; 4 | 5 | public class TestStream { 6 | public static void main(String... args) { 7 | Stream stream = Stream.iterate(0, i -> i + 1); 8 | stream.findFirst().ifPresent(System.out::println); 9 | stream.findFirst().ifPresent(System.out::println); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise12/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise12 2 | 3 | import io.kotlintest.properties.forAll 4 | import io.kotlintest.specs.StringSpec 5 | 6 | class StreamTest: StringSpec() { 7 | 8 | init { 9 | 10 | "head&tail" { 11 | forAll { a: Int -> 12 | val stream = Stream.from(a) 13 | val first = stream.head().getOrElse(0) 14 | val second = stream.tail().getOrElse(Stream.invoke()).head().getOrElse(0) 15 | first == a && second == a + 1 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise13/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise13 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "dropAtMost&takeAtMost" { 12 | forAll(Gen.choose(0, 100_000), Gen.choose(0, 500)) { a, offset -> 13 | val stream = Stream.from(a).dropAtMost(offset).takeAtMost(offset) 14 | stream.isEmpty() || stream.head().map { it == a + offset }.getOrElse(false) 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise14/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise14 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "dropAtMost&takeAtMost" { 12 | forAll(Gen.choose(0, 100_000), Gen.choose(0, 500)) { a, offset -> 13 | val stream = Stream.from(a).dropAtMost(offset).takeAtMost(offset) 14 | stream.isEmpty() || stream.head().map { it == a + offset }.getOrElse(false) 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise15/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise15 2 | 3 | import com.fpinkotlin.common.range 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class StreamTest: StringSpec() { 9 | 10 | init { 11 | 12 | "toList" { 13 | forAll(10, Gen.choose(0, 1_000)) { a -> 14 | val list = range(0, a) 15 | val stream = Stream.from(0).takeAtMost(a) 16 | list.toString() == stream.toList().toString() 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise16/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise16 2 | 3 | import com.fpinkotlin.common.range 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class StreamTest: StringSpec() { 9 | 10 | init { 11 | 12 | "iterate" { 13 | forAll(10, Gen.choose(0, 1_000)) { a -> 14 | val list = range(0, a) 15 | val stream = Stream.iterate(0) { it + 1 }.takeAtMost(a) 16 | list.toString() == stream.toList().toString() 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise22/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise22 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "headSafeViaFoldRight" { 12 | forAll(Gen.choose(0, 100_000), Gen.choose(0, 500)) { a, offset -> 13 | val stream = Stream.from(a).dropAtMost(offset).takeAtMost(offset) 14 | stream.isEmpty() || stream.headSafeViaFoldRight().map { it == a + offset }.getOrElse(false) 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise26/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise26 2 | 3 | import com.fpinkotlin.common.range 4 | import io.kotlintest.properties.Gen 5 | import io.kotlintest.properties.forAll 6 | import io.kotlintest.specs.StringSpec 7 | 8 | class StreamTest: StringSpec() { 9 | 10 | init { 11 | 12 | "flatMap" { 13 | forAll(10, Gen.choose(0, 1_000)) { a -> 14 | fun inc(i: Int) = i + 1 15 | val list = range(0, a) 16 | val stream = Stream.iterate(Lazy{ inc(-1) }, ::inc).takeWhileViaFoldRight { it < a }.flatMap { Stream.from(it).takeAtMost(1) } 17 | list.toString() == stream.toList().toString() 18 | } 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise27/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise27 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "find" { 12 | forAll(Gen.choose(0, 1_000)) { a -> 13 | val stream = Stream.from(0).takeAtMost(a) 14 | stream.find { it == a / 2 }.getOrElse(0) == a / 2 && 15 | stream.find { it == a * 2 }.getOrElse(-1) == -1 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise28/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise28 2 | 3 | import io.kotlintest.properties.Gen 4 | import io.kotlintest.properties.forAll 5 | import io.kotlintest.specs.StringSpec 6 | 7 | class StreamTest: StringSpec() { 8 | 9 | init { 10 | 11 | "fibs" { 12 | forAll(Gen.choose(3, 50)) { a -> 13 | val stream = fibs() 14 | val r1 = stream.dropAtMost(a - 1).head() 15 | val r2 = stream.dropAtMost(a - 2).head() 16 | val r3 = stream.dropAtMost(a - 3).head() 17 | r1.flatMap { x -> r2.flatMap { y -> r3.map { z -> z + y == x } } }.getOrElse(false) 18 | } 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /fpinkotlin-parent/fpinkotlin-workingwithlaziness-solutions/src/test/kotlin/com/fpinkotlin/workingwithlaziness/exercise29/StreamTest.kt: -------------------------------------------------------------------------------- 1 | package com.fpinkotlin.workingwithlaziness.exercise29 2 | 3 | import com.fpinkotlin.common.Result 4 | import com.fpinkotlin.common.range 5 | import io.kotlintest.properties.Gen 6 | import io.kotlintest.properties.forAll 7 | import io.kotlintest.specs.StringSpec 8 | 9 | class StreamTest: StringSpec() { 10 | 11 | init { 12 | 13 | "unfold" { 14 | forAll(10, Gen.choose(0, 1_000)) { a -> 15 | val list = range(0, a) 16 | val stream = Stream.unfold(-1) { Result(Pair(it + 1, it + 1)) }.takeAtMost(a) 17 | list.toString() == stream.toList().toString() 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /fpinkotlin-parent/gradle.properties: -------------------------------------------------------------------------------- 1 | projectVersion = 1.0-SNAPSHOT 2 | projectGroup = com.fpinkotlin 3 | 4 | # dependencies 5 | kotlinVersion = 1.3.72 6 | kotlintestVersion = 3.1.10 7 | slf4jVersion = 1.7.25 8 | logbackVersion = 1.2.3 9 | #junitVersion = 3.1.8 10 | kotlinReflectVersion = 1.3.71 11 | kotlintestJunitVersion = 3.4.2 12 | kotlinCoroutinesVersion = 1.3.3 13 | 14 | # options 15 | kotlin.code.style = official 16 | 17 | # cache 18 | org.gradle.caching = true 19 | -------------------------------------------------------------------------------- /fpinkotlin-parent/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/fpinkotlin-parent/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /fpinkotlin-parent/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /graphics/ImportProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/graphics/ImportProject.png -------------------------------------------------------------------------------- /graphics/RunTest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/graphics/RunTest.png -------------------------------------------------------------------------------- /graphics/RunTest1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/graphics/RunTest1.png -------------------------------------------------------------------------------- /graphics/failedTest01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/graphics/failedTest01.png -------------------------------------------------------------------------------- /graphics/failedTest02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/graphics/failedTest02.png -------------------------------------------------------------------------------- /graphics/successTest03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pysaumont/fpinkotlin/bbc69f859993e37a0554cae29bb33b8e82e1f61c/graphics/successTest03.png --------------------------------------------------------------------------------