tag:blogger.com,1999:blog-32559230236029276172024-03-14T10:11:26.078-07:00Ken BarclayKen Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.comBlogger33125tag:blogger.com,1999:blog-3255923023602927617.post-75006413730662221022022-10-28T07:30:00.000-07:002022-10-28T07:30:23.448-07:00Kotlin: Functional Domain Modeling #6<p> <b style="font-family: arial; font-size: x-large;">Kotlin: Functional Domain Modeling #6</b></p><div><br /></div><div><div style="text-align: justify;"><i>In this blog we introduce the repository: a storage place for the principal aggregates of an application. The repository provides a persistent storage for the aggregates and support for retrieval from the store. Usually, a repository has an implementation based on a relational database management system. In this blog we keep the repository as a simple in-memory storage so that in the next blog we can explore injecting it into the services of an application.</i></div><div style="text-align: justify;"><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial; text-align: justify;">Repositories</b></div><div><br /></div><div style="text-align: justify;"><i>Repositories </i>are where the larger aggregates of the application live. The nature of the repository structures do not need to fully match that of the aggregate but you can always construct an aggregate from the repository. The repository also supports querying it for a particular aggregate. Here, the aggregate in our library application is a cataloged book.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Here is a simple API for the cataloged book repository:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">typealias Error = String</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">interface LibraryRepositoryIF {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun store(book: CatalogBook): Either<Error, CatalogBook></span></div><div><span style="font-family: arial; font-size: x-small;"> fun remove(id: String): Either<Error, CatalogBook></span></div><div><span style="font-family: arial; font-size: x-small;"> fun contains(predicate: (String) -> Boolean): Boolean</span></div><div><span style="font-family: arial; font-size: x-small;"> fun contains(id: String): Boolean =</span></div><div><span style="font-family: arial; font-size: x-small;"> contains{iden: String -> (iden == id)}</span></div><div><span style="font-family: arial; font-size: x-small;"> fun lookUp(id: String): Option<CatalogBook></span></div><div><span style="font-family: arial; font-size: x-small;"> fun adjust(id: String, f: (CatalogBook) -> CatalogBook): Either<Error, CatalogBook></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LibraryRepositoryIF</span></div><div><br /></div><div>Note that we have kept the return types of the functions as <b>Either </b>to account for the possible failures that might occur when interacting with the repository.</div><div><br /></div><div>From here we can have specific implementations to match the chosen storage mechanism. The following is an simple implementation based on the Dogs <b>Map </b>type. The <b>Map </b>class is implemented as a simple balanced binary tree. The library also includes a <b>Map </b>class under the package <b>hamt</b>. The Hash Array Mapped Trie is a structure for organizing data in a broadly-branching tree. The high-branching factor results in the data being stored in a a very shallow tree structure resulting in improved performance over the balanced binary tree representation.</div><div><br /></div><div>This implementation for the <b>LibraryRepository </b>might, in turn, be used as a mocking repository during testing. Here is the in-memory variant:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">object LibraryRepository : LibraryRepositoryIF {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> override fun store(book: CatalogBook): Either<Error, CatalogBook> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val catalogBook: Option<CatalogBook> = library.lookUpKey(book.catalogNumber)</span></div><div><span style="font-family: arial; font-size: x-small;"> return catalogBook.fold(</span></div><div><span style="font-family: arial; font-size: x-small;"> {</span></div><div><span style="font-family: arial; font-size: x-small;"> library = library.insert(book.catalogNumber, book)</span></div><div><span style="font-family: arial; font-size: x-small;"> right(book)</span></div><div><span style="font-family: arial; font-size: x-small;"> },</span></div><div><span style="font-family: arial; font-size: x-small;"> { left("LibraryRepository.store: existing book with catalog number: ${book.catalogNumber}") }</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> } // store</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> // ...</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">// ---------- properties ----------------------------------</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> // key is catalog number</span></div><div><span style="font-family: arial; font-size: x-small;"> var library: Map<String, CatalogBook> = MapF.empty()</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LibraryRepository</span></div></div><div><br /></div><div>We show the implementation for function <b>store</b>. First, it looks up the book's catalog number as the key into the <b>Map</b>, returning an Option<CatalogBook>. The generic Option<A> class includes the <b>fold </b>member function with the signature:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <B> fold(none: () -> B, some: (A) -> B): B</span></div><div><br /></div><div>The first parameter function <b>none </b>is called if the receiving <b>Option </b>is a <b>None</b>. The second parameter function <b>some </b>is called if the receiving <b>Option </b>is a <b>Some </b>with its wrapped value as parameter. In function <b>store </b>we call <b>fold </b>on the <b>catalogBook </b>object. If its a <b>None </b>then we know no such book already exists, and we insert the book into the map and return as a success operation. If it is a <b>Some </b>then we return as a failure.</div><div><br /></div><div>The following test results in a successful storing of a cataloged book:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">val catalogBook: CatalogBook =</span></div><div><span style="font-family: arial; font-size: x-small;"> CatalogBook(</span></div><div><span style="font-family: arial; font-size: x-small;"> "book0001",</span></div><div><span style="font-family: arial; font-size: x-small;"> Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> "Kotlin in Action",</span></div><div><span style="font-family: arial; font-size: x-small;"> "Manning",</span></div><div><span style="font-family: arial; font-size: x-small;"> LocalDate.of(2017, 1, 1),</span></div><div><span style="font-family: arial; font-size: x-small;"> ISBN("9781617293290"),</span></div><div><span style="font-family: arial; font-size: x-small;"> NonEmptyListF.of(</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("JEMEROV"), FirstName("Dmitry"), none()), 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("ISAKOVA"), FirstName("Svetlana"), none()), 1992)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> DeweyClassification("005"),</span></div><div><span style="font-family: arial; font-size: x-small;"> LocalDate.now()</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> right(catalogBook),</span></div><div><span style="font-family: arial; font-size: x-small;"> repo.store(catalogBook)</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div><div>The next test fails because we attempt to store a book with the same catalog number twice.</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">val catalogBook: CatalogBook =</span></div><div><span style="font-family: arial; font-size: x-small;"> CatalogBook(</span></div><div><span style="font-family: arial; font-size: x-small;"> "book0001",</span></div><div><span style="font-family: arial; font-size: x-small;"> Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> "Jetpack Compose",</span></div><div><span style="font-family: arial; font-size: x-small;"> "RayWenderlich Tutorial Team",</span></div><div><span style="font-family: arial; font-size: x-small;"> LocalDate.of(2017, 1, 1),</span></div><div><span style="font-family: arial; font-size: x-small;"> ISBN("9781950325122"),</span></div><div><span style="font-family: arial; font-size: x-small;"> NonEmptyListF.of(</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("BALINT"), FirstName("Tine"), none()), 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("BUKETA"), FirstName("Denis"), none()), 1992)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> DeweyClassification("005"),</span></div><div><span style="font-family: arial; font-size: x-small;"> LocalDate.now()</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> left("LibraryRepository.store: existing book with catalog number: book0001"),</span></div><div><span style="font-family: arial; font-size: x-small;"> repo.store(catalogBook)</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial;">Populating the repository</b></div></div><div><br /></div><div style="text-align: justify;">In this latest version, the <b>LibraryRepository </b>is pre-populated with four books so we can perform our tests without having to repeatedly create and populate the repository. For that we use the Kotlin <i>init block</i>. During the initialization of an instance, Kotlin executes the initializer block(s) and property initializer(s) in the same order as they appear in the class/object body. Thus we have:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">object LibraryRepository : LibraryRepositoryIF {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> // ...</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">// ---------- properties ----------------------------------</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> // key is catalog number</span></div><div><span style="font-family: arial; font-size: x-small;"> var library: Map<String, CatalogBook> = MapF.empty()</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> init {</span></div><div><span style="font-family: arial; font-size: x-small;"> val catalogBooks: List<CatalogBook> = ListF.of(</span></div><div><span style="font-family: arial; font-size: x-small;"> CatalogBook(</span></div><div><span style="font-family: arial; font-size: x-small;"> "book0001",</span></div><div><span style="font-family: arial; font-size: x-small;"> Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> "Kotlin in Action", // two copies</span></div><div><span style="font-family: arial; font-size: x-small;"> "Manning",</span></div><div><span style="font-family: arial; font-size: x-small;"> LocalDate.of(2017, 1, 1),</span></div><div><span style="font-family: arial; font-size: x-small;"> ISBN("9781617293290"),</span></div><div><span style="font-family: arial; font-size: x-small;"> NonEmptyListF.of(</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("JEMEROV"), FirstName("Dmitry"), OptionF.none()), 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("ISAKOVA"), FirstName("Svetlana"), OptionF.none()), 1992)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> DeweyClassification("005"),</span></div><div><span style="font-family: arial; font-size: x-small;"> LocalDate.of(2020, 2, 2)</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> // ...</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> library = catalogBooks.foldLeft(MapF.empty()){lib, cBook -> lib.insert(cBook.catalogNumber, cBook)}</span></div><div><span style="font-family: arial; font-size: x-small;"> </span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LibraryRepository</span></div><div><br /></div><div><div><div><br /></div><div><br /></div><div><b style="font-family: arial;">Invariants and laws</b></div></div><div style="text-align: left;"><br /></div><div>A functional domain model is characterized as a series of functions that operate on a set of types and honor a number of invariants. The sets are the data types that form the model. The functions that operate on the data types are published as the API to the user. When we define the operations in an API, the invariants define the relationships between these operations.</div></div><div><br /></div><div>We need to capture some of the invariants that our APIs have to honor. They can be generic constraints or they can be derived from the domain. One of the basic laws that we should enforce for our repository is: for all cataloged books if we store one in the repository then immediately remove it then it will no longer be present in the repository.</div><div><br /></div><div><span style="background-color: white; color: black;">The KwikCheck test framework for Kotlin (<a href="https://kenbarclay.blogspot.com/2020/05/kotlin-property-based-testing.html">as described here</a>) is modeled after the QuickCheck framework. Property-based testing is </span><i style="background-color: white;">generative testing</i><span style="background-color: white; color: black;">. You do not supply specific example inputs with expected outputs as with unit tests. Instead, you define properties about the code and use the generative-testing engine to create randomized inputs to ensure the defined properties are correct. KwikCheck allows us to express these properties and generate the randomized inputs.</span></div><div><span style="background-color: white; color: black;"><br /></span></div><div><span style="background-color: white; color: black;"><i>Property-based testing</i> is a technique where your tests describe the properties and behavior you expect your code to have, and the testing framework tries to find inputs that violate those expectations. Rather than testing a function against specific inputs we try to reason about its behavior over a range of inputs.</span></div><div><span style="background-color: white; color: black;"><br /></span></div><div><span style="background-color: white; color: black;"><div>Test properties are presented as logical propositions. For example, for all library repositories <b>repo </b>and all cataloged books <b>bk </b>the following proposition is a statement that affirms or denies the predicate:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">repo.store(bk).remove(bk.catalogNumber).contains(bk.catalogNumber) ==> false</span></div><br style="text-align: left;" /><div>We test this property embedded in a Unit test framework. The <b>forAll </b>function accepts a generator that produces a randomized <b>CatalogBook </b>containing property values. The generated <b>CatalogBook </b>is captured in the lambda parameter<b> </b>as <b>catalogBook</b>. Function <b>prop </b>expects a predicate for our logical proposition and wraps it into a <b>Property </b>instance. Function <b>check</b> then runs the test and delivers a <b>CheckResult </b>value which, since we are using a Unit test harness, we can complete with an assert.</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">val property = forAll(genCatalogBook){catalogBook -></span></div><div><span style="font-family: arial; font-size: x-small;"> repo.store(catalogBook)</span></div><div><span style="font-family: arial; font-size: x-small;"> repo.remove(catalogBook.catalogNumber)</span></div><div><span style="font-family: arial; font-size: x-small;"> val found: Boolean = repo.contains(catalogBook.catalogNumber)</span></div><div><span style="font-family: arial; font-size: x-small;"> prop(!found)</span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div><div><span style="font-family: arial; font-size: x-small;">val checkResult = property.check()</span></div><div><span style="font-family: arial; font-size: x-small;">assertTrue(checkResult.isPassed())</span></div><div><br /></div><div>The property we are checking require that all store/remove operations pair on the repository with any arbitrary <b>CatalogBook </b>means the book is not in the repository. We establish the <b>genCatalogBook </b>binding for a Gen<CatalogBook> that delivers a random but valid <b>CatalogBook</b>.</div><div><br /></div><div>The core of the KwikCheck library comprises the classes <b>Gen<A></b> and <b>Property</b>. The class <b>Gen<A></b> is the generator class for values of type A. The class <b>Property </b>represents an algebraic property that may be checked for its truth. Its most important member function is <b>check </b>which delivers a result.</div><div><br /></div><div>Here is the binding for <b>genCatalogBook</b>:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">val genCatalogBook: Gen<CatalogBook> = genCatalogNumber.bind{ nbr -></span></div><div><span style="font-family: arial; font-size: x-small;"> genBook.bind{bk -></span></div><div><span style="font-family: arial; font-size: x-small;"> GenF.value(CatalogBook(nbr, bk, DeweyClassification("005"), LocalDate.now()))</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div><div><br /></div><div>The <b>Gen </b>class is <i>monadic </i>and supports the <b>bind</b> operation. As shown, we generate a valid catalog number with <b>genCatalogNumber</b>, bind it to the lambda parameter <b>nbr</b>, we then generate a valid <b>Book </b>instance with <b>genBook </b>and bind it to parameter <b>bk</b>, finally creating a valid <b>CatalogBook</b>.</div><div><br /></div><div>Continuing in a similar manner we produce <b>genCatalogNumber</b>:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">val genCatalogNumber: Gen<String> = GenF.genPosInt(1, 9999).bind{ nbr -></span></div><div><span style="font-family: arial; font-size: x-small;"> val suffix: String = "0000$nbr".takeLast(4)</span></div><div><span style="font-family: arial; font-size: x-small;"> GenF.value("book$suffix")</span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div><div><br /></div><div>and so on.</div><div><br /></div><div>A typical instance produced by <b>genCatalogNumber </b>is:</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">CatalogBook(</span></div><div><span style="font-family: arial; font-size: x-small;"> catalogNumber=book2256, </span></div><div><span style="font-family: arial; font-size: x-small;"> book=Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> title=iwsdxtptcighjjnUlxCdmfskpiFdtaaszwgvklHfv,</span></div><div><span style="font-family: arial; font-size: x-small;"> publisher=ajfxOrgzpcgnrotxutsgjmyciptequiqdnUvpwksxIwrfkqsvppafhUrySwuljuoxzgodioupnrrjgezqveEoss,</span></div><div><span style="font-family: arial; font-size: x-small;"> publicationDate=2003-09-21,</span></div><div><span style="font-family: arial; font-size: x-small;"> isbn=ISBN(isbn=1677465921),</span></div><div><span style="font-family: arial; font-size: x-small;"> authors=[</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(</span></div><div><span style="font-family: arial; font-size: x-small;"> name=Name(</span></div><div><span style="font-family: arial; font-size: x-small;"> lastName=LastName(lastName=EBCHRBHWVR),</span></div><div><span style="font-family: arial; font-size: x-small;"> firstName=FirstName(firstName=Edjpftzfefm),</span></div><div><span style="font-family: arial; font-size: x-small;"> middleName=None</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> yearOfBirth=1996</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(</span></div><div><span style="font-family: arial; font-size: x-small;"> name=Name(</span></div><div><span style="font-family: arial; font-size: x-small;"> lastName=LastName(lastName=ZAWNMYDAQS),</span></div><div><span style="font-family: arial; font-size: x-small;"> firstName=FirstName(firstName=Uriygbbzcfl),</span></div><div><span style="font-family: arial; font-size: x-small;"> middleName=None</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> yearOfBirth=2003</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> ]</span></div><div><span style="font-family: arial; font-size: x-small;"> ), </span></div><div><span style="font-family: arial; font-size: x-small;"> dewey=DeweyClassification(dewey=005), </span></div><div><span style="font-family: arial; font-size: x-small;"> openDate=2022-10-28, </span></div><div><span style="font-family: arial; font-size: x-small;"> withdrawnDate=None</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div><div>The title and publisher are randomly generated strings, the publication date is randomly generated from 2000 to 2020, the ISBN is generated from the 10-digit ISBN. Note how the last names are randomly generated fully capitalized alphabetic strings, while the first names are randomly generated alphabetic strings with a leading capital. All these domain generators are derived from the many base generators provided by KwikCheck.</div></div></div></div></div></span></div></div><div style="text-align: justify;"><div><br /></div><div><br /></div><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><br /><br style="background-color: white; color: #19191c; text-align: left;" /></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-78455122825216445542022-10-27T08:18:00.001-07:002022-10-30T06:13:14.220-07:00Kotlin: Functional Domain Modeling #5<p> <b style="font-family: arial; font-size: x-large;">Kotlin: Functional Domain Modeling #5</b></p><div><br /></div><div><div style="text-align: justify;"><i>In this blog we introduce the traversable pattern. Traversable structures are collections of elements that can be operated upon with an effectful visitor operation. The visitor function performs a side-effect on each element and composes those side effects whilst retaining the original structure.</i></div><div style="text-align: justify;"><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial; text-align: justify;">Traversables</b></div><div><br /></div><div style="text-align: justify;">This is how our <b>Book </b>class appears:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">data class Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> val title: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val publisher: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val isbn: ISBN,</span></div><div><span style="font-family: arial; font-size: x-small;"> val authors: NonEmptyList<Author></span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Using the smart constructor idiom we have (for the <b>Book </b>class):</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun create(</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;"> title: String,</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;"> publisher: String,</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;"> isbn: String,</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;"> vararg authors: ValidationNel<String, Author></span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">): ValidationNel<String, Book></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Note the <b>authors </b>parameter to function <b>create</b>. It is marked as a <b>vararg </b>so we can pass a variable number of actual parameters at the call site, including none. The type is ValidationNel<String, Author> and represents the effectful validation returned from calls to the smart constructor Author.create.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Here is the complete class declaration:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><div><span style="font-family: arial; font-size: x-small;">data class Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> val title: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val publisher: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val isbn: ISBN,</span></div><div><span style="font-family: arial; font-size: x-small;"> val authors: NonEmptyList<Author></span></div><div><span style="font-family: arial; font-size: x-small;">) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(title: String, publisher: String, isbn: String, vararg authors: ValidationNel<String, Author>): ValidationNel<String, Book> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val vISBN: ValidationNel<String, ISBN> = ISBN.create(isbn)</span></div><div><span style="font-family: arial; font-size: x-small;"> val vAuthors: ValidationNel<String, Array<Author>> =</span></div><div><span style="font-family: arial; font-size: x-small;"> if (authors.isEmpty())</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel("Book.create: must have one or more authors")</span></div><div><span style="font-family: arial; font-size: x-small;"> else</span></div><div><span style="font-family: arial; font-size: x-small;"> authors.sequenceValidationNel()</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return fmap2(vISBN, vAuthors){isn: ISBN, auths: Array<Author> -></span></div><div><span style="font-family: arial; font-size: x-small;"> Book(title, publisher, isn, auths.toNonEmptyList())</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Book</span></div></div><div><br /></div><div>Within the body of the <b>create </b>function of class <b>Book </b>the vararg parameter <b>authors </b>is considered an Array<ValidationNel<String, Author>>. The binding for <b>vAuthors </b>is a failure if this array is empty. If <b>authors </b>is non-empty then the binding for <b>vAuthors </b>is to:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">authors.sequenceValidationNel()</span></div><div><br /></div><div>We shall return to this shortly.</div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial;">The iterator pattern</b></div><div><br /></div><div><div>Perhaps the most familiar of the <i>object oriented design patterns</i> is the <i>iterator </i>pattern, which provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. Traditionally, this is achieved by identifying an <i>iterator </i>interface that presents operations to initialize an iteration, to access the current element, to advance to the next element, and to test for completion; collection objects are expected to implement this interface.</div></div><div><br /></div><div><div>This traditional version of the pattern is sometimes called an <i>external iterator</i>. An alternative <i>internal iterator</i> approach assigns responsibility for managing the traversal to the collection instead of the client: the client needs only to provide an operation, which the collection applies to each of its elements.</div></div><div><br /></div><div>Now recall the idea behind the functor function <b>fmap</b>. When we use <b>fmap</b>, we can take any functor structure (such as <b>List </b>or <b>Option </b>from the Dogs library) and transform all the underlying elements of that functor, returning a new object with the exact same structure, but different elements. The new elements might be of the same type or they can be entirely different.</div><div><br /></div><div><i>Traversable </i>structures are containers of elements that can be operated upon with an <i>effectful visitor</i> operation. The visitor function performs a side-effect on each element of the structure and composes these side effects with an applicative. The traversable abstracts this capability with the <b>traverse </b>function:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> F<A>.traverse(f: (A) -> G<B>): G<F<B>></span></div><div><br /></div><div>Once again <b>F </b>is the place-marker for the actual type for which it applies. The types <b>Option</b>, <b>Either</b>, <b>Validation</b>, <b>Array</b>, <b>List </b>and <b>Map </b>from the Dogs library all support the traversable. The function parameter transforms an element from the context using an applicative. Thus <b>G </b>is expected to be some applicative type such as <b>Option</b>, <b>Validation</b> or <b>List</b>.</div><div><br /></div><div>We have already been performing traversals with the functor function <b>fmap </b>and the foldable function <b>foldMap</b>. Function <b>fmap </b>walks across the collection, applies a transformer operation to each element and collects the results by rebuilding the collection. Similarly, function <b>foldMap </b>walks across the collection applies the transforming function and collects the results by combining them with the given monoid. Function <b>traverse </b>provides a further useful way for traversing a collection.</div><div><br /></div><div>As a comparison consider iterating across a list using <b>fmap </b>and the Option-encoded test for negative <b>Int</b>s:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">fun deleteIfNegative(n: Int): Option<Int> =</span></div><div><span style="font-family: arial; font-size: x-small;"> if (n < 0) none() else some(n)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> ListF.of(none(), some(3), some(2), none(), some(0)),</span></div><div><span style="font-family: arial; font-size: x-small;"> ListF.of(-5, 3, 2, -1, 0).fmap(::deleteIfNegative)</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div><div>By contrast, function <b>traverse </b>creates an applicative summary of the contexts within a structure, and then rebuilds the structure in the new context.</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> none(),</span></div><div><span style="font-family: arial; font-size: x-small;"> ListF.of(-5, 3, 2, -1, 0).traverseOption(::deleteIfNegative)</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> some(ListF.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),</span></div><div><span style="font-family: arial; font-size: x-small;"> ListF.closedRange(1, 10).traverseOption(::deleteIfNegative)</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div><div>Given <b>deleteIfNegative</b>, a function that returns an <b>Option </b>effect, function <b>traverseOption </b>threads this effect through the running of this function on all the values in the <b>List</b>, returning a List<Int> in an <b>Option </b>context.</div><div><br /></div><div>Alongside function <b>traverse</b>, the traversable also includes the function <b>sequence</b>:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A> F<G<A>>.sequence(): G<F<A>></span></div><div><br /></div><div>This function threads all the <b>G </b>effects through the <b>F </b>structure and inverts the structure from F<G<A>> to G<F<A>>. Two examples are:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(some(ListF.of(1, 2, 3)), ListF.of(some(1), some(2), some(3)).sequenceOption())</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(none(), ListF.of(some(1), some(2), none()).sequenceOption())</span></div></div><div><br /></div><div>Function <b>sequence </b>turns the traversable inside out.</div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial;">The travesrsable Array</b></div><div><br /></div><div>The <b>Array </b>extension function <b>sequenceValidationNel</b> has the signature:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <E, B> Array<ValidationNel<E, B>>.sequenceValidationNel(): ValidationNel<E, Array<B>></span></div><div><br /></div><div>The function threads all the <b>ValidationNel </b>effects through the <b>Array </b>structure to invert the structure into an ValidationNel<E, Array<B>>. So we turn an Array<ValidationNel<E, B>> into a ValidationNel<E, Array<B>>. The functional community consider <b>sequence </b>as a member of the <i>traversable pattern</i>. Function <b>sequence </b>is somewhat analogous to performing a <i>fold </i>operation - it creates an <i>applicative summary</i> of the contexts (the <b>ValidationNel</b>) within a structure (the <b>Array</b>), and then rebuilds the structure (the <b>Array</b>) in the new context (the <b>ValidationNel</b>).</div><div><br /></div><div>In function <b>create</b> of class <b>Book</b> we use function <b>sequenceValidationNel </b>to traverse the array of ValidationNel<String, Author> produced by the function Author.create. A simple test is:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> successNel(</span></div><div><span style="font-family: arial; font-size: x-small;"> Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> "Kotlin in Action", "Manning", ISBN("9781617293290"),</span></div><div><span style="font-family: arial; font-size: x-small;"> NonEmptyListF.of(</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("JEMEROV"), FirstName("Dmitry"), none()), 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("ISAKOVA"), FirstName("Svetlana"), none()), 1995)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> Book.create("Kotlin in Action", "Manning", "9781617293290",</span></div><div><span style="font-family: arial; font-size: x-small;"> Author.create("JEMEROV", "Dmitry", "", 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author.create("ISAKOVA", "Svetlana", "", 1995)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div><div><div><br /></div><div><br /></div><div><div>The code for the Dogs library can be found at:</div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><br style="background-color: white; color: #19191c; text-align: left;" /></div></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-40059624931325728902022-10-09T09:02:00.004-07:002023-02-09T06:31:29.313-08:00Kotlin: Functional Domain Modeling #0<p> <b style="font-family: arial; font-size: x-large;">Kotlin: Functional Domain Modeling #0</b></p><div><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><i>In this blog we start investigating how to use the Kotlin type system to accurately capture application domain models in code. We will see that types can act as documentation; documentation that does not get out of sync with the design because the latter is represented in the code itself.</i></div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial;">Functions</b></div><div><br /></div><div>In functional programming, the concept of a <i>pure function</i> is one that holds the following properties:</div><div><ul style="text-align: left;"><li>The function is defined solely in terms of its parameters.</li><li>The function should always return the same result for the same input parameters.</li><li>The function should not cause any side effects by mutating any external state.</li></ul></div><div style="text-align: justify;">In other words, a pure function has no observable effect on the execution of the program other than to compute its result given its inputs; it has no side effects. One familiar pure function is the <b>length </b>function of a <b>String</b>. For any given string, the same length is always returned.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Functional programming (FP) is based on this simple premise: we construct our programs using only pure functions. This raises many issues for those with an OO background: how do we program without mutating state; how do we write programs that loop; how do we handle errors without throwing exceptions; how do we program with I/O. Over the course of these blogs we will show how to express all our programs without side effects. We will see how pure functions are easier to test, reuse and reason about.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><div>Important in FP is the notion of <i>higher order functions:</i> functions that are parameters to other functions. We see that functions can also be the results of executing functions. In this way we create functions as values in our executing program, rather than defining them directly.</div><div><br /></div><div><div>Through functions as parameters and functions as results we are able to fully exploit the machinery of these general functions, such as function composition. The resulting function definitions can be both more concise and more readable than traditional approaches.</div><div><br /></div><div><div>This capability is important for a number of reasons. Having higher order functions means that you can eliminate entire categories of functions for a standard data structure by building general mechanisms that traverse the structures and apply higher order functions to each element. By enabling functions as return values, we have the opportunity to build dynamic, adaptable systems.</div></div></div></div><div><br /></div></div><div style="text-align: justify;">A common technique in FP is the concept of <i>currying</i>. Currying is the process of transforming a function of multiple parameters into a series of functions, each of which accepts a single parameter. We call a curried function with its single parameter as in f(a). This in turn delivers another function also requiring a single parameter as in f(a)(b). This continues until all the parameters have been provided. The Dogs library includes constructs to curry given functions.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Closely related to curried functions is the notion of <i>partial function application</i>. When we partially apply a curried function by providing some of the parameters the result is a function which may have the required signature that we can supply to a higher order function.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Functions are the building blocks that can be <i>composed </i>to build other functions. For example, consider the function that converts a <b>String </b>into an <b>Int</b>, and the function that converts an <b>Int</b> into a <b>Boolean</b>. Using function composition we can build larger functions out of smaller ones. We can compose these two functions to create one that converts a <b>String </b>into a <b>Boolean</b>. Whilst Kotlin does not support function composition out of the box, it provides enough features that we can create the support ourselves. This feature is provided by the Dogs library.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b style="font-family: arial; text-align: left;">Managing side effects</b></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In a banking application consider the function to <b>open </b>a new <b>Account</b>. The function may expect various parameters that define the properties of the <b>Account </b>such as the account number, the initial balance, the date the account is opened, etc. One would automatically expect the return type for <b>open </b>to be an <b>Account </b>type. But then the <b>open</b> function could fail because of validation errors. For example, the opening date may be before the current date. In the functional world we do not throw exceptions and expect users to catch them.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The Dogs library offers abstractions that helps address the issue of exceptions. You manage exceptions as <i>effects </i>that compose along with other abstractions in your domain model. An effect adds capabilities to your computation so you do not need to use side effects.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">An <i>effectful computation</i> adds some capabilities to a computation. An effect is modeled with a type constructor that incorporates these additional capabilities. For example the <b>open</b> function might return the type Either<String, Account> which adds the effect of giving a <b>String</b> error in the event of failure otherwise the <b>Account</b> is wrapped in an <b>Either</b>.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b style="font-family: arial; text-align: left;">Algebraic data types</b></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">An <i>algebraic data type</i> (ADT) is a kind of composite type: a type formed by combining other types. Two examples of algebraic types are <i>product types</i> (record types) and <i>sum types</i> (variant types). An ADT is a data types defined by one or more data constructors, each of which may contain zero or more type arguments. We say that the data type is the <i>sum </i>of its data constructors, and each data constructor is the <i>product </i>of its type arguments. These ideas map directly to constructs in Kotlin. The sum type is captured by Kotlin's sealed class, and the product type by a simple class declaration.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">ADTs define the structure of data in your model. Sum types and product types provide the necessary abstractions for structuring the various data of our domain models. Sum types let you model the variations within a data type, product types help to cluster related data into larger abstractions.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">An advantage of working with ADTs is that the compiler validates the various tags to ensure it contains valid combinations of data types. The compiler enforces the rules you have defined for an ADT.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b style="font-family: arial; text-align: left;">Immutability</b></div><div><br /></div><div style="text-align: justify;">One essential characteristic of FP is that all data is <i>immutable</i>: an object whose state cannot be modified after it is created. This is in contrast to a <i>mutable </i>object which can be modified after it is created. This is typical of how a Java programmer would develop his code. FP encourages immutability and eschews in-place mutation.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In Kotlin once you define an immutable ADT you cannot modify any of its properties. To effect a change you create another abstraction from the original with the modified property. For example, we might represent a bank <b>Account </b>with a number an a balance property. The function <b>credit </b>would have an amount to be credited as parameter. The function would return another <b>Account </b>with the same number and a balance obtained from adding the original balance and the credit amount.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The data types provided by the Dogs library are all immutable. The library includes immutable <b>List</b>s, immutable <b>Option</b>s, immutable <b>MultiMap</b>s, etc. Imperative data structures are <i>ephemeral </i>in the sense that making a change to the structure destroys the old version leaving only the new version. A distinctive property of functional data structures is that they are <i>persistent</i> - updating a persistent functional data structure does not destroy the existing version, but creates a new version that coexists with the old one. Because nodes in the data structure are never modified, all nodes that are unaffected by an update can be shared between the old and the new version without worrying that a change in one will be visible to the other. Dogs data types are immutable and persistent.</div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial;">Modeling Simple Values</b></div><div><br /></div><div style="text-align: justify;">As developers we have a tendency to focus on technical issues. However, the domain experts for whom we are developing an application think in terms of domain concepts such an order id, a product code, a customer name or a customer address. If we are to have a successful project it is important that we, as developers, fully embrace the domain experts requirements. To do that we must use the same vocabulary. So, instead of thinking in terms of <b>Int </b>and <b>String</b>, we think in terms of order id and address, even where the order id is an <b>Int</b> and the address is a <b>String</b>.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">As our development proceeds it is important that a product code and a name are not mixed up. Just because they are both represented by <b>String</b>s, say, they are not interchangeable. To make clear these types are distinct we employ a <i>wrapper type</i> that wraps the primitive representation. In an application, the classes <b>ProductCode</b> and <b>Name </b>would be wrapper classes around a <b>String</b>. Creating simple types like this ensures that they cannot be accidentally mixed.</div><div style="text-align: justify;"><br /></div><div><div style="text-align: justify;"><span style="background-color: white; color: #19191c;"><span style="font-family: inherit;">However, wrapper classes introduce a runtime overhead due to additional heap allocations. Moreover, if the wrapped type is primitive, the performance hit is terrible, because primitive types are usually heavily optimized by the runtime, while their wrappers don't get any special treatment. </span></span><span style="background-color: white; color: #19191c; font-family: inherit; text-align: start;">To solve such issues, Kotlin introduces a special kind of class called the </span><em class="article__em" id="5666073d" style="background-color: white; border: 0px; color: #19191c; font-family: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: start; vertical-align: baseline;">inline class</em><span style="background-color: white; color: #19191c; font-family: inherit; text-align: start;">. </span><span style="background-color: white; color: #19191c; font-family: inherit; text-align: left;">At runtime, instances of the inline class will be represented using this single property. </span><span style="background-color: white; color: #19191c; font-family: inherit; text-align: left;">This is the main feature of inline classes, which inspired the name </span><em class="article__em" id="bda856e6" style="background-color: white; border: 0px; color: #19191c; font-family: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;">inline</em><span style="background-color: white; color: #19191c; font-family: inherit; text-align: left;">: data of the class is </span><em class="article__em" id="c50362e6" style="background-color: white; border: 0px; color: #19191c; font-family: inherit; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;">inlined</em><span style="background-color: white; color: #19191c; font-family: inherit; text-align: left;"> into its usages (similar to how the content of <i>inlined functions</i> </span><span style="background-color: white; color: #19191c; font-family: inherit; text-align: left;">is inlined to call sites).</span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="background-color: white; text-align: left;"><span><div style="color: #19191c; text-align: justify;">Almost always simple types are constrained in some way, such as having to be in a certain range or match a certain pattern. It is very unusual to have an unbound <b>Int </b>or <b>String </b>in a real-world domain. For example, a customer last name may be represented by a string, but that does not mean that it should contain a tab character or a symbolic character such as #.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">The standard technique for constructing objects that need to honour a set of constraints is known as the <i>smart constructor idiom</i>. You prohibit the user from invoking the standard constructor and instead provide a factory function that ensures the user gets a data type from which she can recover a valid instance or a reason for failure. This would be an example of an effectful computation. Thereafter, because the data is immutable, the value never needs to be checked again.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><b style="color: black; font-family: arial; text-align: left;">Modeling Aggregate Values</b></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">We said that <span style="color: black;">product types help to aggregate related data into larger abstractions. The clustering is represented by a Kotlin class. The individual class properties might themselves be represented by other ADTs. Consider a banking application with a customer <b>Account</b> class that contains properties such as the customer <b>Address </b>and the <b>Date</b> the account was opened. If the <b>Account</b>, <b>Address</b> and <b>Date </b>properties are immutable, then to change a customer's address we need to make the change at the aggregate <b>Account </b>level, not at the level of the <b>Address</b>.</span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;"><br /></span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;">The aggregate acts as the <i>consistency boundary</i>: when one part of the aggregate is updated, others might also require updating to ensure consistency. For example, in an order taking system, an aggregate <b>Order </b>might have a number of <b>OrderLine</b>s and might have a total price property. If one order line changes its unit price then the total must be updated to keep the <b>Order </b>data consistent.</span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;"><br /></span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;">The aggregate is also where <i>invariants </i>are enforced. In our order taking example, there might be a business rule that any <b>Order </b>must have at least one <b>OrderLine</b>. If we try to delete multiple <b>OrderLine</b>s from an <b>Order </b>then we must ensure there is at least one <b>OrderLine </b>remaining.</span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;"><br /></span></div><div style="text-align: justify;"><span style="color: black;">Nested data structures are a pain to inspect and change. The pain increases with the depth of the data structures. The most common functional approach is to avoid in-place mutation and generate a new instance instead with the updated values. Kotlin's data classes provide syntactic sugar for this operation. Consider the classes:</span></div><div style="text-align: justify;"><span style="color: black;"><br /></span></div><div style="text-align: justify;"><span style="color: black;"><div><span style="font-family: arial; font-size: x-small;">data class Address(val streetNumber: Int, val streetName: String)</span></div><div><span style="font-family: arial; font-size: x-small;">data class Person(val name: String, val age: Int, val address: Address)</span></div><div><br /></div><div>val addr = Address(10, "High Street")</div><div>val newAddr = addr.copy(streetNumber = 11)</div><div><br /></div><div>delivers a new Address instance with the streetNumber as 11 and the streetName as High Street.</div><div><br /></div><div>We update the street number of for the address of a specific person using the same approach:</div><div><br /></div><div>val per = Person("Ken", 25, addr)</div><div>val newPer = per.copy(address = per.address.copy(streetNumber = 11))</div><div><br /></div><div>The greater the level of nesting of the objects, the more cluttered the syntax becomes. This situation demands a better abstraction and is provided by lenses. We can describe a <i>lens </i>as a group of functions that allows us to manipulate data inside a deeply nested class structure.</div></span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;"><br /></span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;"><br /></span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;"><br /></span></div><div style="color: #19191c; text-align: justify;"><b style="color: black; font-family: arial; text-align: left;">Enforcing invariants with the type system</b></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">An invariant is a condition that is always true. A business application might require that a customer last name must be all uppercase letters. That is an example of an invariant. Of course, the smart constructor is one technique to ensure invariants are honoured at the point of creation.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">An <b>Order </b>comprises a number of <b>OrderLine</b>s. A business requirement is that there must always be at least one <b>OrderLine </b>in an <b>Order</b>. We can capture this invariant in the type system if we use the class <b>NonEmptyList </b>rather than the more usual <b>List</b> class. The <b>NonEmptyList </b>class is provided by the custom Dogs library.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">A customer <b>Name </b>might be presented as a product type comprising a <b>LastName</b>, a <b>FirstName </b>and a possible <b>MiddleName</b>. The Dogs library supports the <b>Option </b>type and we might use Option<MiddleName> to ensure the correct semantics.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><b style="color: black; font-family: arial; text-align: left;">Functional patterns in domain models</b></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">Functional design patterns are reusable abstractions. Object oriented design patterns are also reusable abstractions that are examples of best-practice. OO design patterns offer standard solutions for problems that occur repeatedly in programming. However the OO programmer has no code from which to develop a solution, but has to implement the patterns against the problem domain and will have to do this repeatedly each time the pattern is deployed. OO design patterns offer little reusability.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">Functional design patterns offer much more reusability than their OO counterparts. Each functional pattern includes generic and reusable code which is invariant across the contexts where they are used. Context specific implementations are provided for instances where the pattern is applied which can be deployed in application code. Further, these patterns are accompanied with a set of laws. All instances of such patterns are expected to behave in a certain way and satisfy the laws associated with the respective implementations.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><span style="color: black;">The KwikCheck test framework for Kotlin (<a href="https://kenbarclay.blogspot.com/2020/05/kotlin-property-based-testing.html">as described here</a>) is modeled after the QuickCheck framework. Property-based testing is </span><i style="color: black;">generative testing</i><span style="color: black;">. You do not supply specific example inputs with expected outputs as with unit tests. Instead, you define properties about the code and use the generative-testing engine to create randomized inputs to ensure the defined properties are correct. KwikCheck allows us to express these properties and generate the randomized inputs. We use KwikCheck to test the functional design pattern laws on the instances of the pattern. </span><span style="color: black;">The KwikCheck test framework is built on the Dogs library.</span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;"><br /></span></div><div style="color: #19191c; text-align: justify;"><span style="color: black;">We also use KwikCheck to verify the properties of our domain models. As an example, when we model the transfer of funds between two customer accounts in a banking application, a domain rule for this is the amount debited from one account must equal the amount credited to the other. We can think of this domain rule as a property that must be verified for a transfer operation.</span></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">We are familiar with the <b>map </b>function from the <b>List </b>class which applies a transformer function to each element in the <b>List</b> and delivers a new <b>List </b>of transformed values. Because <b>List</b>, <b>Option</b>, etc all share this behavior, we can document it this way as an extension function, in which <b><span style="font-size: medium;">F </span></b>is a place-marker for the actual types for which it applies:</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun <A, B> </span><span style="font-family: arial; font-size: medium;">F</span><span style="font-family: arial; font-size: x-small;"><A>.fmap(f: (A) -> B): </span><span style="font-family: arial; font-size: medium;">F</span><span style="font-family: arial; font-size: x-small;"><B></span></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">This is called a <i>functor </i>and abstracts the capability of mapping over a data type with a regular function. If <b><span style="font-size: medium;">F </span></b>is <b>List</b> then we expect the <b>List </b>extension function:</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun <A, B> List<A>.fmap(f: (A) -> B): List<B></span></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">In the Dogs library the data types <b>Option</b>, <b>Either</b>, <b>List</b>, <b>Map</b> and others are functors and have their implementation for function <b>fmap</b>.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">The signature for <b>fmap </b>might suggest it would be a member function of a <b>Functor </b>interface which the data types <b>Option</b>, <b>Either</b>, <b>List </b>etc would implement. However, in such an interface, <b>F </b>would be a generic type so that F<A> and F<B> would give rise to what are called <i>higher-kinded types</i> that Kotlin does not support.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">One immediate use for this abstraction is to discover other useful functions. If we have an F<Pair<A, B>> we can distribute the <b>F </b>over the <b>Pair </b>to get a Pair<F<A>, F<B>>. Again, with <b>F </b>the <b>List </b>type:</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun <A, B> List<Pair<A, B>>.distribute(): Pair<List<A>, List<B>> =</span></div><div style="color: #19191c; text-align: justify;"><span><span style="font-family: arial; font-size: x-small;"> Pair(this.fmap{pr -> pr.first}, this.fmap{pr -> pr.second})</span></span><br /></div><div style="color: #19191c;"><br /></div><div style="color: #19191c;">We get two <b>List</b>s of the same length, one with all the <b>A</b>s and one with all the<b> B</b>s.</div><div style="color: #19191c;"><br /></div><div style="color: #19191c;">In a library application we might have the following functions:</div><div style="color: #19191c;"><br /></div><div style="color: #19191c;"><span style="font-family: arial; font-size: x-small;">fun classifiedBooks(dewey: String): List<Book> = ...</span></div><div style="color: #19191c;"><span style="font-family: arial; font-size: x-small;">fun isWithdrawn(book: Book): Boolean = ...</span></div><div style="color: #19191c;"><br /></div><div style="color: #19191c; text-align: justify;">Function <b>classifiedBooks </b>returns a <b>List</b> of <b>Book</b>s that match the dewey decimal classification. Function <b>isWithdrawn </b>determines if the given <b>Book </b>has been withdrawn from service. We can now use <b>fmap </b>to implement a domain specific behavior:</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun withdrawnByClassification(dewey: String): List<Boolean> =</span></div><div style="color: #19191c; text-align: justify;"><span style="font-family: arial; font-size: x-small;"> classifiedBooks(dewey).fmap(::isWithdrawn)</span></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">The functor is just one of many functional design patterns we include in the Dogs library.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><span style="color: black;">A second functional design patterns is known as the <i>monad </i>and is defined for various types</span><span style="color: black;"> defined in the Dogs library. </span><span style="color: #222222; text-indent: 48px;">Monads allow the programmer to build up computations using sequential building blocks. </span><span style="color: #222222; text-indent: 48px;">The monad determines how combined computations form a new computation and frees the programmer from having to code the combination manually each time it is required. It is useful to think of a monad as a strategy for combining computations into more complex computations.</span></div><div style="color: #19191c; text-align: justify;"><span style="color: #222222; text-indent: 48px;"><br /></span></div><div style="color: #19191c; text-align: justify;">Again, we document this as an extension function <b>bind</b>, in which <b><span style="font-size: medium;">F </span></b>is the place-marker for the actual types for which it applies:</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun <A, B> </span><span style="font-family: arial; font-size: medium;">F</span><span style="font-family: arial; font-size: x-small;"><A>.bind(f: (A) -> </span><span style="font-family: arial; font-size: medium;">F</span><span style="font-family: arial; font-size: x-small;"><B>): </span><span style="font-family: arial; font-size: medium;">F</span><span style="font-family: arial; font-size: x-small;"><B></span></div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;">It looks similar to the function <b>fmap </b>defined for the functor. The only difference is the signature of the function <b>f </b>that <b>bind </b>takes as parameter. For function <b>fmap </b>the function parameter returns a value, but for function <b>bind </b>it returns an instance of the type of the monad, here <b><span style="font-size: medium;">F</span></b>. When you apply <b>f </b>to the receiver type F<A> in <b>bind</b>, you effectively end up with F<F<B>>. However, <b>bind </b>then flattens them into a single F<B>. Semantically, <b>bind </b>is equivalent to an <b>fmap </b>operation followed by a <b>flatten</b> operation. For this reason <b>bind </b>is often also known by the name <b>flatMap</b>.</div><div style="color: #19191c; text-align: justify;"><br /></div><div style="color: #19191c; text-align: justify;"><div>The basic intuition behind the <b>bind </b>operation is that it allows us to combine two computations into one more complex computation and allows them to interact with one another. The receiver type F<A> represents the first computation. Significantly, the parameter type of <b>bind </b>is (A) -> F<B> which can, given the result of the first computation, produce a second computation to run. In other words fa.bind{a -> ... } is a computation which runs <b>fa </b>(some instance of type F<A>) and binds the value wrapped in <b>fa </b>to the function literal parameter <b>a</b>. The function body then decides what computation to run using the value for <b>a</b>.</div><div><br /></div><div>The monad also includes a second function <b>inject</b>. Function <b>inject </b>lets us put a value into a monadic context. For example, for the <b>List </b>type <b>inject </b>is the same as creating a <b>List </b>with a single element. Often <b>inject </b>is simply the class constructor. Its signature is:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A> inject(a: A): </span><span style="font-family: arial; font-size: medium;">F</span><span style="font-family: arial; font-size: x-small;"><A></span></div><div><br /></div><div>The Dogs library supports these functions for the data types <b>Option</b>, <b>Either</b>, <b>List</b>, <b>NonEmptyList</b>, etc. </div><div><br /></div><div>Consider the function <b>divide </b>which returns an optional integer Option<Int>. If the numerator is exactly divisible by the denominator the function succeeds and returns their quotient wrapped in a <b>Some</b>, otherwise it fails and returns a <b>None</b>. <b>Some </b>and <b>None </b>are the concrete implementations of the <b>Option </b>type and are created with the factory functions <b>some </b>and <b>none</b>.</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">fun divide(num: Int, den: Int): Option<Int> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return if (num % den != 0) none() else some(num / den)</span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div></div><div><br /></div><div>Consider now the function <b>bindDivision </b>which returns an optional pair of integers if the first two parameters are exactly divisible by the third parameter. The returned pair are quotients of the first and third parameter, and the second and third parameter.</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">fun bindDivision(a: Int, b: Int, c: Int): Option<Pair<Int, Int>> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return divide(a, c).bind{ac: Int -></span></div><div><span style="font-family: arial; font-size: x-small;"> divide(b, c).bind{bc: Int -></span></div><div><span style="font-family: arial; font-size: x-small;"> inject(Pair(ac, bc))</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div></div><div><br /></div><div>Consider the implementation of <b>bindDivision</b>. The outer call to divide(a, c).bind{ ac -> ...} has an <b>Option </b>value produced from the expression divide(a, c). Should this be a <b>Some </b>value, then the function literal is called and its formal parameter ac is bound to the result from the <b>Some </b>value. In the inner call divide(b, c).bind{ bc -> ...} the inner function literal is called with the formal parameter bc bound to the <b>Some </b>value produced from divide(b, c). If the two calls to <b>divide </b>both deliver <b>Some </b>values then a final <b>Some </b>result is produced carrying the pair we seek. If a <b>None </b>value is delivered by either call to <b>divide </b>then a <b>None</b> value is the final result.</div><div><br /></div><div><div>Functional languages use monads to turn complicated sequences of functions into succinct pipelines that abstract away control flow, and side-effects. The programmer composes a sequence of function calls (a pipeline) with several <b>bind </b>operators chained together in an expression. Each function call transforms its input plain-type value, and the <b>bind </b>operator handles the returned monadic value, which is fed into the next step in the sequence. The side effect of the <b>divide </b>function returning <b>None </b>is automatically handled. The <b>bind </b>function only executes the following operation if the value is a <b>Some </b>value, otherwise it just passes the <b>None </b>along.</div></div><div><br /></div><div>In later blogs we shall explore other functional design patterns such as the <i>applicative functor</i>, the <i>foldable</i>, the <i>traversable </i>alongside others. These patterns forms the basis of effectful computation in programming. They offer abstractions for handling effects within the domain models we develop. We will demonstrate the support provided by the custom Dogs library.</div></div><div style="color: #19191c;"><br /></div><div style="color: #19191c;"><br /></div><div style="color: #19191c;"><br /></div><div style="color: #19191c;"><div style="color: black; text-align: justify;">The code for the Dogs library can be found at:</div><div style="color: black; text-align: justify;"><br /></div><span style="color: black;"><div style="text-align: justify;">https://github.com/KenBarclay/TBA</div></span><span style="color: black;"><div style="text-align: justify;">https://github.com/KenBarclay/TBA</div></span></div><div style="color: #19191c;"><br /></div><div style="color: #19191c;"><br /></div><div style="color: #19191c;"><br /></div></span></span></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-63309981748576039662022-04-06T06:39:00.005-07:002022-10-13T07:45:00.600-07:00Kotlin: Functional Domain Modeling #4<p> <b style="font-family: arial; font-size: x-large;">Kotlin: Functional Domain Modeling #4</b></p><div><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><i>In this blog we introduce the foldable pattern. Foldable structures are collections of elements that can be folded to a summary value.</i></div><div style="text-align: justify;"><br /></div><div><br /></div><div><br /></div><div><span style="font-family: arial;"><b>Collections</b></span></div><div><br /></div><div style="text-align: justify;">An <i>invariant </i>is a condition that stays true no matter what else happens. For example, we have said that the last name of an author must be fully capitalized. Consider now a class representing a library book. We expect the book to have an ISBN, a title, a publisher, and at least one author. This last condition is an example of an invariant that can be captured directly in the type system. To ensure that we have one or more book authors, we use the <b>NonEmptyList </b>class. The definition of this class requires that there must always be at least one element, and never empty. With this change, the constraint that there is always at least one author is now enforced automatically. The code is self-documenting and there is no need to write unit tests for this requirement.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">This is how our <b>Book </b>class appears:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">data class Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> val title: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val publisher: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val isbn: ISBN,</span></div><div><span style="font-family: arial; font-size: x-small;"> val authors: NonEmptyList<Author></span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Using the smart constructor idiom we have (for the <b>Book </b>class):</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun create(title: String, publisher: String, isbn: String, vararg authors: Author): ValidationNel<String, Book></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Note the <b>authors </b>parameter to function <b>create</b>. It is marked as a <b>vararg </b>so we can pass a variable number of actual parameters of type <b>Author </b>at the call site, including none.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Here is the complete class declaration:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><div><span style="font-family: arial; font-size: x-small;">data class Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> val title: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val publisher: String,</span></div><div><span style="font-family: arial; font-size: x-small;"> val isbn: ISBN,</span></div><div><span style="font-family: arial; font-size: x-small;"> val authors: NonEmptyList<Author></span></div><div><span style="font-family: arial; font-size: x-small;">) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(title: String, publisher: String, isbn: String, vararg authors: Author): ValidationNel<String, Book> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val vISBN: ValidationNel<String, ISBN> = ISBN.create(isbn)</span></div><div><span style="font-family: arial; font-size: x-small;"> return if (authors.isEmpty())</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel("Book: at least one author required")</span></div><div><span style="font-family: arial; font-size: x-small;"> else {</span></div><div><span style="font-family: arial; font-size: x-small;"> val list: List<Author> = ListF.from(*authors)</span></div><div><span style="font-family: arial; font-size: x-small;"> vISBN.fmap{isbn: ISBN -></span></div><div><span style="font-family: arial; font-size: x-small;"> Book(title, publisher, isbn, NonEmptyListF.from(list))</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Book</span></div></div><div><br /></div><div>The class <b>ISBN </b>is formulated as per the classes <b>LastName</b>, <b>FirstName</b>, etc. Within the body of the <b>create </b>function of class <b>Book </b>the vararg parameter <b>authors </b>is considered an Array<Author> and is transformed into a List<Author> from the Dogs library.</div><div><br /></div><div>The following assert shows successfully creating a <b>Book </b>with two authors:</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> successNel(</span></div><div><span style="font-family: arial; font-size: x-small;"> Book(</span></div><div><span style="font-family: arial; font-size: x-small;"> "Kotlin in Action", "Manning", ISBN("9781617293290"),</span></div><div><span style="font-family: arial; font-size: x-small;"> NonEmptyListF.of(</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("JEMEROV"), FirstName("Dmitry"), none()), 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("ISAKOVA"), FirstName("Svetlana"), none()), 1995)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;"> ),</span></div><div><span style="font-family: arial; font-size: x-small;"> Book.create("Kotlin in Action", "Manning", "9781617293290",</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("JEMEROV"), FirstName("Dmitry"), none()), 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("ISAKOVA"), FirstName("Svetlana"), none()), 1995)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div></div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial;">The Foldable</b></div></div><div style="text-align: justify;"><div><br /></div><div>Given the authors for an individual book we might wish to implement the following behaviors: (a) compute the sum of each author's age; (b) identify the oldest age among the authors. Although the details of the two behaviors we desire, some similarity exists. For example, in both we will have to process each individual author in the collection of authors.</div><div><br /></div><div>The foldable type represents structures that can be folded to a summary value. In the case of a collection (such as <b>List </b>or <b>Vector </b>from Dogs) the functions will fold together (combine) the values contained in the collection to produce a single result. The <i>foldable </i>abstracts this capability and is implemented with two basic functions:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> F<A>.foldLeft(e: B, f: (B) -> (A) -> B): B</span></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> F<A>.foldRight(e: B, f: (A) -> (B) -> B): B</span></div><div><br /></div><div>Both functions are overloaded with variants that accept the function parameter in its uncurried form. Consider the simple list [1, 2, 3]. You sum the numbers of this list with 0 as the initial value (<b>e</b>) and the integer addition operation for <b>f</b>. Since <b>foldLeft </b>is left-associative, the execution of this fold would be ((0 + 1) + 2) + 3. Using a <b>foldRight </b>would evaluate as 0 + (1 + (2 + 3)). Since integer addition is associative, both yield the same result. For non-associative operations, the functions can produce differing results. Here are two simple examples:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(25, ListF.of(5, 4, 8, 6, 2).foldLeft(0){ sum, elem -> sum + elem})</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(105, ListF.of(1, 3, 5, 7).foldRight(1){elem, prod -> prod * elem})</span></div></div><div><br /></div><div>The use-cases for our book example might be implemented as:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">object Analytics {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun totalAges(authors: NonEmptyList<Author>): Int {</span></div><div><span style="font-family: arial; font-size: x-small;"> fun age(author: Author): Int = LocalDate.now().year - author.yearOfBirth</span></div><div><span style="font-family: arial; font-size: x-small;"> return authors.foldLeft(0){ages: Int, author: Author -> ages + age(author)}</span></div><div><span style="font-family: arial; font-size: x-small;"> } // totalAges</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun oldest(authors: NonEmptyList<Author>): Int {</span></div><div><span style="font-family: arial; font-size: x-small;"> fun age(author: Author): Int = LocalDate.now().year - author.yearOfBirth</span></div><div><span style="font-family: arial; font-size: x-small;"> return if (authors.size() == 1)</span></div><div><span style="font-family: arial; font-size: x-small;"> age(authors.head())</span></div><div><span style="font-family: arial; font-size: x-small;"> else</span></div><div><span style="font-family: arial; font-size: x-small;"> authors.foldLeft(age(authors.head())){old: Int, author: Author -> if (age(author) > old) age(author) else old }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // oldest</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Analytics</span></div></div><div><br /></div><div>with the <b>NonEmptyList </b>a foldable. Two tests are:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">val vBook: ValidationNel<String, Book> =</span></div><div><span style="font-family: arial; font-size: x-small;"> Book.create("Kotlin in Action", "Manning", "9781617293290",</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("JEMEROV"), FirstName("Dmitry"), none()), 1992),</span></div><div><span style="font-family: arial; font-size: x-small;"> Author(Name(LastName("ISAKOVA"), FirstName("Svetlana"), none()), 1995)</span></div><div><span style="font-family: arial; font-size: x-small;"> )</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(57, vBook.fold({0}, {book -> Analytics.totalAges(book.authors)})) // in 2022</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(30, vBook.fold({0}, {book -> Analytics.oldest(book.authors)})) // in 2022</span></div></div><div><br /></div><div>The implementations for <b>totalAges </b>and <b>oldest </b>have similarities that we can refactor into more generic patterns. For example: (a) both implement a <i>fold</i> over the collection; (b) both take an <b>Int</b> zero as the seed of the fold and and perform a binary operation on two <b>Int</b>s on each iteration. We can unify these seemingly different functions using a <i>monoid</i>.</div><div><br /></div><div><div><div><br /></div><div><br /></div><div><b style="font-family: arial;">The Monoid</b></div></div><div><div><br /></div><div>Let us consider a simple <i>algebraic structure</i>, the <i>monoid</i>, which is defined only by its algebra. Other than satisfying the same laws, instances of the monoid may have little or nothing to do with one another. Nonetheless, we’ll see how this algebraic structure is often all we need to write useful, polymorphic functions.</div><div><br /></div><div>Monoids are simple, ubiquitous, and useful. Monoids come up all the time in everyday programming, whether we’re aware of them or not. Working with lists, concatenating strings, or accumulating the results of a loop can often be phrased in terms of monoids. We’ll see how monoids are useful to assemble complex calculations from simpler pieces.</div><div><br /></div><div>Consider the algebra of string concatenation. We can add "foo" + "bar" to get "foobar", and the empty string is an identity element for that operation. That is, if we say (s + "") or ("" + s), the result is always s. Furthermore, if we combine three strings by saying (r + s + t), the operation is associative—it doesn’t matter whether we parenthesize it: ((r + s) + t) or (r + (s + t)).</div><div><br /></div><div>The term for this kind of algebra is <i>monoid</i>. The laws of associativity and identity are collectively called the monoid laws. A monoid consists of the following:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">interface Semigroup<A> {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun combine(a: A, b: A): A</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Semigroup</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">interface Monoid<A : Any> : Semigroup<A> {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> val empty: A</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Monoid</span></div></div><div><br /></div><div>where empty is the identity for the combine operation, and combine is an associative binary operation that takes two value of some type and combines them into one value of the same type. The Dogs library presents these two interfaces as well as a range of instances such as <b>stringMonoid</b>, <b>intAdditionMonoid</b>, <b>ListSemigroup</b>, <b>ListMonoid</b>, etc.</div><div><br /></div><div>The implementation for function <b>totalAges </b>implements a fold over the collection with an <b>Int </b>zero as the seed for the fold and a binary addition on two <b>Int</b>s. Using <b>intAddMonoid </b>as an instance of <b>Monoid </b>we can define <b>totalAges </b>with:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">object Analytics {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun totalAges(authors: NonEmptyList<Author>): Int {</span></div><div><span style="font-family: arial; font-size: x-small;"> val mi: Monoid<Int> = intAddMonoid</span></div><div><span style="font-family: arial; font-size: x-small;"> fun age(author: Author): Int = LocalDate.now().year - author.yearOfBirth</span></div><div><span style="font-family: arial; font-size: x-small;"> return authors.foldLeft(mi.empty){ages: Int, author: Author -> mi.combine(ages, age(author))}</span></div><div><span style="font-family: arial; font-size: x-small;"> } // totalAges</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> // ...</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Analytics</span></div></div><div><br /></div><div>The operation within the fold is now an operation on a monoid instead of hardcoded operations on a specific type.</div><div><br /></div><div><div><div><br /></div><div><br /></div><div><b style="font-family: arial;">The Foldable foldMap</b></div></div><div><div><br /></div><div>The foldable type also includes the <b>foldMap </b>function:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> F<A>.foldMap(mb: Monoid<B>, f: (A) -> B): B</span></div><div><br /></div><div>Function <b>foldMap </b>is similar to our earlier fold operations, but maps every value of type <b>A </b>into a value of type <b>B </b>and then combines them using the given monoid. Here is our final version of <b>Analytics</b>:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">object Analytics {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun totalAges(authors: NonEmptyList<Author>): Int {</span></div><div><span style="font-family: arial; font-size: x-small;"> fun age(author: Author): Int = LocalDate.now().year - author.yearOfBirth</span></div><div><span style="font-family: arial; font-size: x-small;"> return authors.foldMap(intAddMonoid, ::age)</span></div><div><span style="font-family: arial; font-size: x-small;"> } // totalAges</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun oldest(authors: NonEmptyList<Author>): Int {</span></div><div><span style="font-family: arial; font-size: x-small;"> val intLargerMonoid: Monoid<Int> = object: Monoid<Int> {</span></div><div><span style="font-family: arial; font-size: x-small;"> override val empty: Int = 0</span></div><div><span style="font-family: arial; font-size: x-small;"> override fun combine(a: Int, b: Int): Int = max(a, b)</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> fun age(author: Author): Int = LocalDate.now().year - author.yearOfBirth</span></div><div><span style="font-family: arial; font-size: x-small;"> return authors.foldMap(intLargerMonoid, ::age)</span></div><div><span style="font-family: arial; font-size: x-small;"> } // oldest</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Analytics</span></div></div><div><br /></div><div>Both functions use <b>foldMap</b>. In function <b>totalAges </b>the <b>intAddMonoid</b> is used to accumulate the individual age of each author. In function <b>oldest </b>the custom <b>intLargerMonoid </b>is defined to find the largest age of each individual author. So given the foldable type NonEmptyList<A>, a type B that is a monoid, and a mapping function between A and B, we package <b>foldMap </b>into a combinator that abstracts the requirements for <b>totalAges </b>and <b>oldest</b>.</div></div></div><div><br /></div></div></div><div><div><br /></div><div><br /></div><div><div>The code for the Dogs library can be found at:</div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><br style="background-color: white; color: #19191c; text-align: left;" /></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-3106259064748099932022-03-31T06:22:00.008-07:002022-11-03T08:25:43.548-07:00Kotlin: Functional Domain Modeling #3<p> <b style="font-family: arial; font-size: x-large;">Kotlin: Functional Domain Modeling #3</b></p><div><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><i>In this blog we introduce the applicative functor pattern. The central idea behind the pattern is the sequencing of effects. Validation is one use case for which applicative functors are useful. Given a series of validation effects, regardless of the result (failure or success) they guarantee all will be executed independently.</i></div><div><br /></div><div><br /></div><div><br /></div><div><span style="font-family: arial;"><b>Applicative functor</b></span></div><div><br /></div><div style="text-align: justify;">Consider filling out a web form to sign up for an account. You enter your user name and password and the system responds by saying that a user name may not contain dashes. When you make the necessary changes and resubmit you might now be informed that the password must have at least one capital letter.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">It would be nice to have all the errors reportedly simultaneously. We have seen that the monadic <b>Either </b>fails fast, reporting the first validation error it detects. Another approach is to use the <b>Validation </b>class that is comparable to <b>Either</b>:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">sealed class Validation<E, A> {</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;"> data class Failure<E, A>(val value: E) : Validation<E, A>()</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;"> data class Success<E, A>(val value: A) : Validation<E, A>()</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">}</span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">in which the type parameter <b>E </b>represents the error type and the type parameter <b>A </b>represents the obtained value.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The following shows validating the <b>LastName </b>with the <b>Validation </b>class replacing our earlier version with <b>Either</b>. Function <b>create </b>returns a <b>Validation </b>object with a <b>String</b> for its error type and <b>LastName </b>for its payload. The asserts show a successful creation and a failure creation.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><div><span style="font-family: arial; font-size: x-small;">data class LastName(val lastName: String) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String): Validation<String, LastName> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return if(lastName.length < 2)</span></div><div><span style="font-family: arial; font-size: x-small;"> failure("Last name too short: $lastName")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (!regex.matches(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> failure("Last name malformed: $lastName")</span></div><div><span style="font-family: arial; font-size: x-small;"> else</span></div><div><span style="font-family: arial; font-size: x-small;"> success(LastName(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> private val regex: Regex = Regex("[A-Z][A-Z]*")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LastName</span></div></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(success(LastName("BARCLAY")), LastName.create("BARCLAY"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(failure("Last name malformed: Barclay"), LastName.create("Barclay"))</span></div></div><div><br /></div><div>The <b>Validation </b>class is accompanied with the <b>typealias</b>:</div><div><br /></div><div>typealias ValidationNel<E, A> = Validation<NonEmptyList<E>, A></div><div><br /></div><div>where the error type for <b>ValidationNel </b>is a <b>NonEmptyList </b>of errors of type <b>E</b>. The <b>NonEmptyList </b>reflects the fact that if there are validation errors then one or more will be reported. <b>ValidationNel </b>is supported with the factory functions <b>failureNel </b>and <b>successNel</b>, substitutes for the functions <b>failure </b>and <b>success</b>.</div><div><br /></div><div>The next example repeats the above, this time using <b>ValidationNel</b>. Note how the failing assert packs the single error into a <b>NonEmptyList</b>.</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">data class LastName(val lastName: String) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String): ValidationNel<String, LastName> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return if(lastName.length < 2)</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel("Last name too short: $lastName")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (!regex.matches(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel("Last name malformed: $lastName")</span></div><div><span style="font-family: arial; font-size: x-small;"> else</span></div><div><span style="font-family: arial; font-size: x-small;"> successNel(LastName(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> private val regex: Regex = Regex("[A-Z][A-Z]*")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LastName</span></div></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(successNel(LastName("BARCLAY")), LastName.create("BARCLAY"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(failureNel("Last name malformed: Barclay"), LastName.create("Barclay"))</span></div></div><div><span style="font-family: arial; font-size: small;">typealias ValidationNelError<A> = ValidationNel<ValidationError, A></span></div><div><br /></div><div>Rebuilding our LastName, FirstName, MiddleName and Name using ValidationNel we have:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName, val middleName: Option<MiddleName> = none()) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String, firstName: String, middleName: String = ""): ValidationNel<String, Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val vLastName: ValidationNel<String, LastName> = LastName.create(lastName)</span></div><div><span style="font-family: arial; font-size: x-small;"> val vFirstName: ValidationNel<String, FirstName> = FirstName.create(firstName)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return if (middleName == "")</span></div><div><span style="font-family: arial; font-size: x-small;"> fmap2(vLastName, vFirstName){ln, fn -> Name(ln, fn) }</span></div><div><span style="font-family: arial; font-size: x-small;"> else {</span></div><div><span style="font-family: arial; font-size: x-small;"> val vMiddleName: ValidationNel<String, MiddleName> = MiddleName.create(middleName)</span></div><div><span style="font-family: arial; font-size: x-small;"> fmap3(vLastName, vFirstName, vMiddleName){ln, fn, mn -> Name(ln, fn, some(mn)) }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(name: String): ValidationNel<String, Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val names: List<String> = name.split(" ")</span></div><div><span style="font-family: arial; font-size: x-small;"> val size: Int = names.size</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return if (size == 0)</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel("Name.create: empty name not supported")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size == 1)</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel("Name.create: name must exceed 1 part")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size > 3)</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel("Name.create: name must not exceed 3 parts")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size == 2) {</span></div><div><span style="font-family: arial; font-size: x-small;"> val vLastName: ValidationNel<String, LastName> = LastName.create(names[0])</span></div><div><span style="font-family: arial; font-size: x-small;"> val vFirstName: ValidationNel<String, FirstName> = FirstName.create(names[1])</span></div><div><span style="font-family: arial; font-size: x-small;"> fmap2(vLastName, vFirstName){ln, fn -> Name(ln, fn)}</span></div><div><span style="font-family: arial; font-size: x-small;"> } else {</span></div><div><span style="font-family: arial; font-size: x-small;"> val vLastName: ValidationNel<String, LastName> = LastName.create(names[0])</span></div><div><span style="font-family: arial; font-size: x-small;"> val vFirstName: ValidationNel<String, FirstName> = FirstName.create(names[1])</span></div><div><span style="font-family: arial; font-size: x-small;"> val vMiddleName: ValidationNel<String, MiddleName> = MiddleName.create(names[2])</span></div><div><span style="font-family: arial; font-size: x-small;"> fmap3(vLastName, vFirstName, vMiddleName){ln, fn, mn -> Name(ln, fn, some(mn)) }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Name</span></div></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div>If all three <b>ValidationNel<String, ...> </b>instances indicate a successful validation we extract the validated arguments and pass them to a pure function <b>f </b>that constructs the validated result object. In case of errors they are reported to the caller of Name.create. The functions that we use are <b>fmap2 </b>and <b>fmap3 </b>with the signature for the former:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <E, A, B, C> fmap2(</span></div><div><span style="font-family: arial; font-size: x-small;"> vea: ValidationNel<E, A>, veb: ValidationNel<E, B>, f: (A, B) -> C</span></div><div><span style="font-family: arial; font-size: x-small;">): ValidationNel<E, C></span></div><div><br /></div><div><div>This is an example of the <i>applicative functor</i> pattern of functional programming. The pattern is used when you deal with effects in functional programming. These <i>applicative effects</i> refer to the way the effects are applied. Our application of <b>fmap3</b> demonstrates that the effects are sequenced through all the validation functions regardless of the failure or success they produce. This is shown in the following asserts:</div></div></div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> successNel(Name(LastName("BARCLAY"), FirstName("Ken"), some(MiddleName("Andrew")))),</span></div><div><span style="font-family: arial; font-size: x-small;"> Name.create("BARCLAY", "Ken", "Andrew")</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel(NonEmptyListF.of("Last name malformed: Barclay")),</span></div><div><span style="font-family: arial; font-size: x-small;"> Name.create("Barclay", "Ken", "Andrew")</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel(NonEmptyListF.of("First name malformed: ken")),</span></div><div><span style="font-family: arial; font-size: x-small;"> Name.create("BARCLAY", "ken", "Andrew")</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel(NonEmptyListF.of("Middle name malformed: andrew")),</span></div><div><span style="font-family: arial; font-size: x-small;"> Name.create("BARCLAY", "Ken", "andrew")</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> failureNel(NonEmptyListF.of("First name malformed: ken", "Middle name malformed: andrew")),</span></div><div><span style="font-family: arial; font-size: x-small;"> Name.create("BARCLAY", "ken", "andrew")</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div><div>The final assert demonstrates how the applicative pattern <i>fails slow</i>, identifying two separate validation failures.</div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial; text-align: left;">The applicative functor</b></div><div><br /></div><div>The functions <b>fmap2 </b>and <b>fmap3 </b>are generalizations of <b>fmap, </b>to functions with more than one parameter. With <b>F </b>the actual data type place-marker, the overloaded function <b>fmap2 </b>has the signatures:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B, C> fmap2(fa: F<A>, fb: F<B>, f: (A) -> (B) -> C): F<C></span></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B, C> fmap2(fa: F<A>, fb: F<B>, f: (A, B) -> C): F<C> = fmap2(fa, fb, C2(f))</span></div><div><br /></div><div>Note how the second version with the function <b>f </b>presented in its uncurried form can be defined in terms of the first version using the Dogs function <b>C2 </b>to curry its function parameter. The Dogs library includes the currying functions <b>C2</b>, <b>C3</b>, <b>C4</b> and <b>C5</b>.</div><div><br /></div><div>Whilst the Dogs library includes functions <b>fmap2</b> and <b>fmap3 </b>across all types that are applicative functors, the question is whether we should also include <b>fmap4</b>, <b>fmap5</b>, etc, making the code very tedious.</div><div><br /></div><div>The solution gives rise to the notion of an <i>applicative functor</i>. With <b>F </b>the place-marker for the actual type for which it applies, the applicative functor is described with the <b>ap </b>extension function (representing sequential application) and the function <b>pure</b>:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> F<A>.ap(f: F<(A) -> B>): F<B></span></div><div><span style="font-family: arial; font-size: x-small;">fun <A> pure(a: A): F<A></span></div><div><br /></div><div>With these two basic functions we can construct any mapping function fmapN. The function <b>pure</b> converts a value of type <b>A </b>into the context F<A>. If the context is, say <b>List</b>,<b> </b>then function <b>pure </b>creates a singleton <b>List </b>with that single value. Function <b>ap</b> is a generalized form of function application. We have a function (A) -> B, a value of type <b>A</b>, and a result of type <b>B</b>, all wrapped in a context <b>F</b>.</div><div><br /></div><div>A typical use of these functions is shown in the following asserts:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(some(3), some(2).ap(pure{m: Int -> m + 1}))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(some(3), pure{m: Int -> m + 1} appliedOver some(2))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(some(5), pure{m: Int -> {n: Int -> m + n}} appliedOver some(2) appliedOver some(3))</span></div></div><div><br /></div><div>The function <b>appliedOver </b>is an infix version of function <b>ap</b> with the function given first. The final assert is often known as the <i>applicative style</i> because of its similarity to normal function application.</div><div><br /></div><div>This final example informs us how we can now define <b>fmap2</b>:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B, C> fmap2(fa: F<A>, fb: F<B>, f: (A) -> (B) -> C): F<C> =</span></div><div><span style="font-family: arial; font-size: x-small;"> pure(f) appliedOver fa appliedOver fb</span></div><div><br /></div><div>We see that whilst we could continue with this to define <b>fmap3</b>, <b>fmap4</b>, etc, we can simply employ the applicative style to get what we require.</div><div><br /></div><div>Here it is defined for the <b>Option </b>type:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">fun <A, B, C> fmap2(oa: Option<A>, ob: Option<B>, f: (A) -> (B) -> C): Option<C> =</span></div><div><span style="font-family: arial; font-size: x-small;"> pure(f) appliedOver oa appliedOver ob</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(some(5), fmap2(some(2), some(3)){m -> {n -> m + n}})</span></div></div><div><br /></div><div><div><div><br /></div><div><br /></div><div><div>The code for the Dogs library can be found at:</div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><br style="background-color: white; color: #19191c; text-align: left;" /></div></div><div><br /></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-78031051242774702222022-03-29T08:08:00.004-07:002022-10-07T08:26:34.504-07:00Kotlin: Functional Domain Modeling #2<p> <b style="font-family: arial; font-size: x-large;">Kotlin: Functional Domain Modeling #2</b></p><div><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><i>In this blog we investigate creation strategies for our domain elements. Factories offer a unified strategy for object creation. But other considerations for object creation include: how do we ensure that the factory returns a valid object; where to put the validation logic; and what happens if the validation fails.</i></div><div><br /></div><div><br /></div><div><br /></div><div><span style="font-family: arial;"><b>The Integrity of Simple Values</b></span></div><div><br /></div><div style="text-align: justify;">We can create an object in a multitude of ways - the simplest being a direct invocation of the class constructor. But, the simplest technique always has some pitfalls. We need to apply some good software engineering principles when creating domain model objects. We must ensure our object are valid. It is very unusual to have an unbounded <b>Int </b>or <b>String </b>in a real world domain. In the previous blog our product id was represented by an <b>Int </b>but it is unlikely that the business uses a negative <b>Int</b>. Equally, the last name for a customer is represented by a <b>String</b>, but we would not expect it to include a tab character.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">We see some of these issues in the following code. The class represents someones last name but there are no constraints on what values we provide.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">class LastName(val lastName: String)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">val me = LastName("BARCLAY")</span></div><div><span style="font-family: arial; font-size: x-small;">val doppelganger = LastName("Ken")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals("BARCLAY", me.lastName)</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals("Ken", doppelganger.lastName)</span></div></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">We want to ensure the values of these types cannot be created unless they satisfy the domain constraints. Thereafter, because the object is immutable, the value never needs to be checked again.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">To ensure the constraints are enforced we make the constructor private/internal and provide a separate function that creates only valid values. The standard technique for the construction of objects that honors some constraint is known as the <i>smart constructor</i> idiom. Here is an example:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">@JvmInline</span></div><div><span style="font-family: arial; font-size: x-small;">value class LastName private constructor(val lastName: String) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(text: String): LastName = LastName(text)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LastName</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">// compilation error: cannot access private LastName</span></div><div><span style="font-family: arial; font-size: x-small;">// val me = LastName("BARCLAY")</span></div><div><span style="font-family: arial; font-size: x-small;">val doppelganger = LastName.create("Barclay")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals("Barclay", doppelganger.lastName)</span></div><div><br /></div><div>So now the <b>LastName </b>object cannot be created due to the private constructor. This is shown in the commented code. The <b>create </b>function is our (not yet) smart constructor factory function.</div><div><br /></div><div>In functional programming, an <i>effect </i>adds some capabilities to a computation. An effect is modeled in the form of a <i>type constructor</i> that constructs types with additional capabilities. Consider some arbitrary type <b>LastName</b>, then, for example, Option<LastName> adds optionality to the type <b>LastName</b>.</div><div><br /></div><div>In the next example the smart constructor function <b>create </b>makes two checks on the text supplied for the name. If the text contains only one character or if the text is not all uppercase letters then <b>None </b>is returned to indicate that a valid name could not be constructed. Otherwise, a <b>LastName </b>object is created and wrapped in a <b>Some </b>to denote success.</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">data class LastName(val lastName: String) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String): Option<LastName> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return if(lastName.length < 2)</span></div><div><span style="font-family: arial; font-size: x-small;"> none()</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (!regex.matches(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> none()</span></div><div><span style="font-family: arial; font-size: x-small;"> else</span></div><div><span style="font-family: arial; font-size: x-small;"> some(LastName(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> private val regex: Regex = Regex("[A-Z][A-Z]*")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LastName</span></div></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(some(LastName("BARCLAY")), LastName.create("BARCLAY"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(none(), LastName.create("Barclay"))</span></div><div><br /></div><div><div><br /></div><div><br /></div><div><span style="font-family: arial;"><b>Managing failure with Option type</b></span></div><div><br /></div><div>In a business application a customer name is modeled as a last name and a first name. Like above the last name is expected to be fully capitalized. The first name is expected to have a leading capital letter and any number of lowercase letters. Here is class <b>FirstName </b>modeled as earlier:</div><div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">data class FirstName(val firstName: String) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(firstName: String): Option<FirstName> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return if(firstName.length < 2)</span></div><div><span style="font-family: arial; font-size: x-small;"> none()</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (!regex.matches(firstName))</span></div><div><span style="font-family: arial; font-size: x-small;"> none()</span></div><div><span style="font-family: arial; font-size: x-small;"> else</span></div><div><span style="font-family: arial; font-size: x-small;"> some(FirstName(firstName))</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> private val regex: Regex = Regex("[A-Z][a-z]*")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // FirstName</span></div></div><div><br /></div><div>The <b>Name </b>class declaration starts with:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName) ...</span></div><div><br /></div><div>It too adopts the smart constructor idiom with its own <b>create</b> function:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String, firstName: String): Option<Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return ...</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Name</span></div><div><br /></div></div><div>The body of the function create will pass <b>lastName </b>to the function LastName.create returning an Option<LastName>, and pass <b>firstName </b>to the function FirstName.create returning an Option<FirstName>. <b>Option </b>is a <i>monad </i>as defined in the Dogs library. <span style="background-color: white; color: #222222; text-indent: 48px;">Monads allow the programmer to build up computations using sequential building blocks. </span><span style="background-color: white; color: #222222; text-indent: 48px;">The monad determines how combined computations form a new computation and frees the programmer from having to code the combination manually each time it is required. It is useful to think of a monad as a strategy for combining computations into more complex computations.</span></div><div><span style="background-color: white; color: #222222; text-indent: 48px;"><br /></span></div><div><span style="background-color: white; color: #222222; text-indent: 48px;">We use Option's <b>bind </b>(aka <b>flatMap</b>) function to compose the results from LastName.create and FirstName.create. This <b>bind </b>function makes <b>Option </b>a monad and helps to compose them in a clean manner. Here is the final version of the <b>Name </b>class:</span></div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create1(lastName: String, firstName: String): Option<Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val oLastName: Option<LastName> = LastName.create(lastName)</span></div><div><span style="font-family: arial; font-size: x-small;"> val oFirstName: Option<FirstName> = FirstName.create(firstName)</span></div><div><span style="font-family: arial; font-size: x-small;"> return oLastName.bind{ln -></span></div><div><span style="font-family: arial; font-size: x-small;"> oFirstName.bind{fn -></span></div><div><span style="font-family: arial; font-size: x-small;"> some(Name(ln, fn))</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create1</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create2(lastName: String, firstName: String): Option<Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val oLastName: Option<LastName> = LastName.create(lastName)</span></div><div><span style="font-family: arial; font-size: x-small;"> val oFirstName: Option<FirstName> = FirstName.create(firstName)</span></div><div><span style="font-family: arial; font-size: x-small;"> return bind2(oLastName, oFirstName,){ln -></span></div><div><span style="font-family: arial; font-size: x-small;"> {fn -></span></div><div><span style="font-family: arial; font-size: x-small;"> some(Name(ln, fn))</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create2</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create3(lastName: String, firstName: String): Option<Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val oLastName: Option<LastName> = LastName.create(lastName)</span></div><div><span style="font-family: arial; font-size: x-small;"> val oFirstName: Option<FirstName> = FirstName.create(firstName)</span></div><div><span style="font-family: arial; font-size: x-small;"> return bind2(oLastName, oFirstName){ln, fn -> some(Name(ln, fn)) }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create3</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(name: String): Option<Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val names: List<String> = name.split(" ")</span></div><div><span style="font-family: arial; font-size: x-small;"> val size: Int = names.size</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return if (size != 2)</span></div><div><span style="font-family: arial; font-size: x-small;"> none()</span></div><div><span style="font-family: arial; font-size: x-small;"> else {</span></div><div><span style="font-family: arial; font-size: x-small;"> val oLastName: Option<LastName> = LastName.create(names[0])</span></div><div><span style="font-family: arial; font-size: x-small;"> val oFirstName: Option<FirstName> = FirstName.create(names[1])</span></div><div><span style="font-family: arial; font-size: x-small;"> bind2(oLastName, oFirstName){ln, fn -> some(Name(ln, fn))}</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Name</span></div></div><div><br /></div><div>The three functions <b>create1</b>, <b>create2 </b>and <b>create3</b> are presented to show the different ways of using <b>bind</b>. Here is the signature of (extension) function <b>bind</b> from the <b>Option </b>class:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> Option<A>.bind(f: (A) -> Option<B>): Option<B></span></div><div><br /></div><div>The <b>bind </b>function operates on an Option<A> along with the function parameter that converts an A into an Option<B>. The result type is an Option<B>. If the Option<A> is a <b>Some </b>then the function parameter is applied to its wrapped value, producing the required result. If the Option<A> is a <b>None </b>then its value is bypassed as a <b>None </b>value.</div><div><br /></div><div>If in Name.create1 the function call LastName.create(lastName) is a <b>Some</b>, then the wrapped <b>LastName </b>is associated with the <b>bind</b> parameter <b>ln</b>. If the function call FirstName.create(firstText) is a <b>Some</b>, then the wrapped <b>FirstName </b>is associated with the bind parameter <b>fn</b>. A <b>Name </b>is created from these two values and wrapped in a <b>Some </b>to denote success.</div><div><br /></div><div>Where the chain of operations involves no other processes then the function <b>bind2 </b>can be used. In function <b>create2 </b>we use the version of <b>bind2 </b>that expects a curried binary function. The overloaded <b>bind2 </b>in <b>create3</b> uses an uncurried function to give the most compact coding.</div><div><br /></div><div>The first assert creates a successful <b>Name</b>. The other assert statements fail with, respectively, invalid last name, invalid first name, and invalid last and first names. Note carefully the final assert. Both names are invalid but only the last name is the cause of the resulting <b>None</b>. The call to LastName.create("Barclay") returns an Option<LastName> which is a <b>None</b>, and the chain of <b>bind</b>s breaks. Calls to FirstName.create("ken") is never executed. For that reason monads are said to <i>fail fast</i>.</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> some(Name(LastName("BARCLAY"), FirstName("Ken"))),</span></div><div><span style="font-family: arial; font-size: x-small;"> Name.create1("BARCLAY", "Ken")</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(none(), Name.create1("Barclay", "Ken")) // bad last name</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(none(), Name.create2("BARCLAY", "ken")) // bad first name</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(none(), Name.create3("BARCLAY", "ken")) // bad last + first name</span></div></div><div><br /></div><div><br /></div><div><br /></div><div><b style="font-family: arial;">The monad</b></div><div><div><br /></div><div>We present a formal definition of the monad through the following two functions. Again, <b>F</b> is a place-marker for the actual type for which it applies:</div><div><br /></div><div>fun <A, B> F<A>.bind(f: (A) -> F<B>): F<B></div><div>fun <A> inject(a: A) -> F<A></div><div><br /></div><div>The <b>bind</b> function is the <i>monadic sequencing operation</i>. If the receiver F<A> produces an <b>A</b>, then <b>bind </b>applies the function <b>f </b>converting it to an F<B>. The function <b>bind </b>returns an F<B>. The <b>inject</b> function is like the applicative <b>pure </b>function and injects a value into the <b>F </b>context.</div><div><br /></div><div>An important aspect of the function <b>bind</b> is understanding how the chaining of computations takes place when you plug multiple <b>bind</b>s together. They compose sequentially, and the chain breaks when one of the <b>bind</b>s break. We saw exactly this when using the <b>Option </b>monad in the smart constructor for the <b>Name </b>class.</div><div><br /></div><div>Here it is defined for the <b>List </b>type:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> List<A>.bind(f: (A) -> List<B>): List<B> =</span></div><div><span style="font-family: arial; font-size: x-small;"> concat(this.fmap(f))</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(ListF.of(-1, 1, -2, 2, -3, 3), ListF.of(1, 2, 3).bind{n -> ListF.of(-n, +n)})</span></div></div><div><br /></div><div>When defining this <b>bind </b>function we have a List<A> as the receiver and a function on the elements of the List: (A) -> List<B>. Then a natural thing to do is to map that function over the <b>List </b>as in the sub-expression this.fmap(f). This sub-expression has the type List<List<B>>. The helper function <b>concat </b>transforms this into a List<B> as required.</div><div><br /></div><div>The next example defines a function <b>pairs </b>that takes two <b>List</b> parameters and returns a <b>List </b>of <b>Pair</b>s of elements from those two <b>List</b>s. The function is expected to deliver all possible pairs from the two <b>List</b>s. Since <b>List</b>s are monadic we can define pairs with:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">fun <A, B> pairs(la: List<A>, lb: List<B>): List<Pair<A, B>> =</span></div><div><span style="font-family: arial; font-size: x-small;"> la.bind{a: A -></span></div><div><span style="font-family: arial; font-size: x-small;"> lb.bind{b: B -></span></div><div><span style="font-family: arial; font-size: x-small;"> inject(Pair(a, b))</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div></div><div><br /></div><div>The first application of <b>bind</b> selects one value from the first list while the second application of <b>bind </b>selects one value from the second list. We then <b>inject </b>the Pair into the result <b>List</b>.</div><div><br /></div><div>The monad as a functional design pattern is, like all others, accompanied with a set of laws which must be satisfied for each implementation. We use KwikCheck to check the monad laws on the monad instances.</div><div><br /></div><div><br /></div><div><br /></div></div></div></div></div></div></div><div><br /></div><div><b style="font-family: arial;">Managing failure with Either type</b></div><div><br /></div><div>Consider the smart constructor function <b>create </b>in the class <b>LastName</b>. Under normal circumstances the caller supplies a capitalized <b>String</b> of at least two characters. But what about the exceptions? Both exceptions report failure by returning <b>None </b>but give no indication of the nature of the error.</div><div><br /></div><div>Our creation process can result in two possible errors: the text is too short or it is not fully capitalized. So to report success for the two types of error we employ the Either<A, B> type which has two type parameters and the two specializations: <b>Left </b>and <b>Right</b>. We inject a value of type A by using the <b>Left</b> constructor, or we inject a value of type B by using the <b>Right </b>constructor. Conventionally, when using <b>Either </b>for validations <b>Left </b>is used to denote failure and <b>Right </b>for success.</div><div><br /></div><div>In the following version of function <b>create</b> we wrap the output with an <b>Either </b>type which returns a <b>String </b>if a problem occurs and a <b>LastName </b>if successful. The first assert is a valid name while the remaining two asserts are malformed names.</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">data class LastName(val lastName: String) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String): Either<String, LastName> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return if(lastName.length < 2)</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Last name too short: $lastName")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (!regex.matches(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Last name malformed: $lastName")</span></div><div><span style="font-family: arial; font-size: x-small;"> else</span></div><div><span style="font-family: arial; font-size: x-small;"> right(LastName(lastName))</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> private val regex: Regex = Regex("[A-Z][A-Z]*")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // LastName</span></div></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(right(LastName("BARCLAY")), LastName.create("BARCLAY"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(left("Last name malformed: Barclay"), LastName.create("Barclay"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(left("Last name too short: B"), LastName.create("B"))</span></div></div><div><br /></div><div>Here is how the <b>Name </b>class when using the <b>Either </b>type:</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String, firstName: String): Either<String, Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val eLastName: Either<String, LastName> = LastName.create(lastName)</span></div><div><span style="font-family: arial; font-size: x-small;"> val eFirstName: Either<String, FirstName> = FirstName.create(firstName)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return bind2(eLastName, eFirstName){ln, fn -> right(Name(ln, fn)) }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(name: String): Either<String, Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val names: List<String> = name.split(" ")</span></div><div><span style="font-family: arial; font-size: x-small;"> val size: Int = names.size</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return if (size == 0)</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Name.create: empty name not supported")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size == 1)</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Name.create: name must exceed 1 part")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size > 3)</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Name.create: name must not exceed 3 parts")</span></div><div><span style="font-family: arial; font-size: x-small;"> else {</span></div><div><span style="font-family: arial; font-size: x-small;"> val eLastName: Either<String, LastName> = LastName.create(names[0])</span></div><div><span style="font-family: arial; font-size: x-small;"> val eFirstName: Either<String, FirstName> = FirstName.create(names[1])</span></div><div><span style="font-family: arial; font-size: x-small;"> bind2(eLastName, eFirstName){ln, fn -> right(Name(ln, fn))}</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Name</span></div></div><div><br /></div><div>We are avoiding using primitives such as <b>String</b>s and instead create domain-specific types. Errors deserve the same treatment and should be modeled like everything else in the domain. To keep our code samples brief we continue to use <b>String</b>s but more typically we might model errors as:</div><div><br /></div><div><span style="font-family: arial; font-size: x-small;">sealed class PaymentError {</span></div><div><span style="font-family: arial; font-size: x-small;"> data class PaymentRejected(val amount: Int) : PaymentError()</span></div><div><span style="font-family: arial; font-size: x-small;"> data class CardTypeNotRecognized(val type: String) : PaymentError()</span></div><div><span style="font-family: arial; font-size: x-small;"> // ...</span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div><div><br /></div><div><div><div><br /></div><div><br /></div><div><b style="font-family: arial;">Modeling Optional Values</b></div><div><br /></div><div>In an application a name is modeled as a last name, a first name and an optional middle name. The last name and the first name are as above. The middle name follows the pattern for the first name. The <b>Option </b>type ensures the correct semantics for a name. Here is the new <b>Name </b>class:</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName, val middleName: Option<MiddleName> = none()) {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(lastName: String, firstName: String, middleName: String = ""): Either<String, Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val eLastName: Either<String, LastName> = LastName.create(lastName)</span></div><div><span style="font-family: arial; font-size: x-small;"> val eFirstName: Either<String, FirstName> = FirstName.create(firstName)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return if (middleName == "")</span></div><div><span style="font-family: arial; font-size: x-small;"> bind2(eLastName, eFirstName){ln, fn -> right(Name(ln, fn, none())) }</span></div><div><span style="font-family: arial; font-size: x-small;"> else {</span></div><div><span style="font-family: arial; font-size: x-small;"> val eMiddleName: Either<String, MiddleName> = MiddleName.create(middleName)</span></div><div><span style="font-family: arial; font-size: x-small;"> bind3(eLastName, eFirstName, eMiddleName){ln, fn, mn -> right(Name(ln, fn, some(mn))) }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> fun create(name: String): Either<String, Name> {</span></div><div><span style="font-family: arial; font-size: x-small;"> val names: List<String> = name.split(" ")</span></div><div><span style="font-family: arial; font-size: x-small;"> val size: Int = names.size</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> return if (size == 0)</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Name.create: empty name not supported")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size == 1)</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Name.create: name must exceed 1 part")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size > 3)</span></div><div><span style="font-family: arial; font-size: x-small;"> left("Name.create: name must not exceed 3 parts")</span></div><div><span style="font-family: arial; font-size: x-small;"> else if (size == 2) {</span></div><div><span style="font-family: arial; font-size: x-small;"> val eLastName: Either<String, LastName> = LastName.create(names[0])</span></div><div><span style="font-family: arial; font-size: x-small;"> val eFirstName: Either<String, FirstName> = FirstName.create(names[1])</span></div><div><span style="font-family: arial; font-size: x-small;"> bind2(eLastName, eFirstName){ln, fn -> right(Name(ln, fn))}</span></div><div><span style="font-family: arial; font-size: x-small;"> } else {</span></div><div><span style="font-family: arial; font-size: x-small;"> val eLastName: Either<String, LastName> = LastName.create(names[0])</span></div><div><span style="font-family: arial; font-size: x-small;"> val eFirstName: Either<String, FirstName> = FirstName.create(names[1])</span></div><div><span style="font-family: arial; font-size: x-small;"> val eMiddleName: Either<String, MiddleName> = MiddleName.create(names[2])</span></div><div><span style="font-family: arial; font-size: x-small;"> bind3(eLastName, eFirstName, eMiddleName){ln, fn, mn -> right(Name(ln, fn, some(mn))) }</span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> }</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">} // Name</span></div></div><div><br /></div><div>The middle name is modeled with <b>Option </b>and is <b>None</b> if absent from the constructor call. The <b>create </b>function chains together three calls to function <b>bind </b>to assemble a valid <b>Name</b>. The following assert statements should be self-explanatory:</div><div><br /></div><div><div><div><span style="font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="font-family: arial; font-size: x-small;"> right(Name(LastName("BARCLAY"), FirstName("Ken"), some(MiddleName("Andrew")))),</span></div><div><span style="font-family: arial; font-size: x-small;"> Name.create("BARCLAY", "Ken", "Andrew")</span></div><div><span style="font-family: arial; font-size: x-small;">)</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(left("Last name malformed: Barclay"), Name.create("Barclay", "Ken", "Andrew"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(left("First name malformed: ken"), Name.create("BARCLAY", "ken", "Andrew"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(left("Middle name malformed: andrew"), Name.create("BARCLAY", "Ken", "andrew"))</span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(left("First name malformed: ken"), Name.create("BARCLAY", "ken", "andrew"))</span></div></div><div><br /></div></div></div></div><div><div><br /></div><div><br /></div><div><div>The code for the Dogs library can be found at:</div><div><br /></div><span style="color: black;"><div>https://github.com/KenBarclay/TBA</div></span><span style="color: black;"><div>https://github.com/KenBarclay/TBA</div></span></div><div><br style="background-color: white; color: #19191c; text-align: left;" /></div></div><div><br /></div></div></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-63182700275238970472022-03-29T08:07:00.002-07:002022-10-06T10:00:29.818-07:00Kotlin: Functional Domain Modeling #1<div style="text-align: left;"><b style="font-family: arial; font-size: x-large;">Kotlin: Functional Domain Modeling #1<br /></b><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><i>In this blog we start investigating how to use the Kotlin type system to accurately capture the domain model in code. We will see that types can act as documentation; documentation that does not get out of sync with the design because the latter is represented in the code itself.</i></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="font-family: arial;"><b>Modeling Simple Values</b></span></div><div style="text-align: left;"><br /></div><div style="text-align: justify;">As developers we have a tendency to focus on technical issues. However, the domain experts for whom we are developing an application think in terms of domain concepts such an order id, a product code, a customer name or a customer address. If we are to have a successful project it is important that we, as developers, fully embrace the domain experts requirements. To do that we must use the same vocabulary. So, instead of thinking in terms of <b>Int </b>and <b>String</b>, we think in terms of order id and address, even where the order id is an <b>Int</b> and the address is a <b>String</b>.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">As our development proceeds it is important that, for example, a product code and a name are not mixed up. Just because they are both represented by <b>String</b>s, say, they are not interchangeable. To make clear these types are distinct we employ a <i>wrapper type</i> that wraps the primitive representation.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In the following the classes <b>CustomerId </b>and <b>OrderId</b> are wrapper classes around a primitive <b>Int</b>. Creating simple types like this ensures that they cannot be accidentally mixed. The final comment line shows we cannot compare them.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">data class CustomerId(val id: Int)</span></div><div><span style="font-family: arial; font-size: x-small;">data class OrderId(val id: Int)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">val customerId = CustomerId(123)</span></div><div><span style="font-family: arial; font-size: x-small;">val orderId = OrderId(456)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">// compilation error: operator == cannot be applied</span></div><div><span style="font-family: arial; font-size: x-small;">// val isSame = (customerId == orderId)</span></div><div><br /></div></div><div style="text-align: justify;">Equally, if we have the function <b>processCustomer </b>that expects a <b>CustomerId </b>as input, then calling that function with an <b>OrderId </b>is another error.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="font-family: arial; font-size: x-small;">val customerId = CustomerId(123)</span></div><div><span style="font-family: arial; font-size: x-small;">val orderId = OrderId(456)</span></div><div><span style="font-family: arial; font-size: x-small;">fun processCustomer(customerId: CustomerId): Unit = TODO()</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">processCustomer(customerId)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">// compilation error: required: CustomerId; found: OrderId</span></div><div><span style="font-family: arial; font-size: x-small;">// processCustomer(orderId)</span></div><div><br /></div><div style="text-align: justify;"><span style="background-color: white; color: #19191c;"><span style="font-family: inherit;">Sometimes it is necessary for business logic to create a wrapper around some type. However, it introduces runtime overhead due to additional heap allocations. Moreover, if the wrapped type is primitive, the performance hit is terrible, because primitive types are usually heavily optimized by the runtime, while their wrappers don't get any special treatment.</span></span></div><div style="text-align: justify;"><span style="background-color: white; color: #19191c;"><span style="font-family: inherit;"><br /></span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span style="background-color: white; color: #19191c; text-align: start;">To solve such issues, Kotlin introduces a special kind of class called the </span><em class="article__em" id="5666073d" style="background-color: white; border: 0px; color: #19191c; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: start; vertical-align: baseline;">inline class</em><span style="background-color: white; color: #19191c; text-align: start;">. </span><span style="background-color: white; color: #19191c; text-align: left;">To declare an inline class, use the <b>value </b></span><span style="background-color: white; color: #19191c; text-align: left;">modifier before the name of the class. </span><span style="background-color: white; color: #19191c; text-align: left;">To declare an inline class for the JVM backend, use the <b>value </b></span><span style="background-color: white; color: #19191c; text-align: left;">modifier along with the @JvmInline </span><span style="background-color: white; color: #19191c; text-align: left;">annotation before the class declaration. </span><span style="background-color: white; color: #19191c; text-align: left;">An inline class must have a single property initialized in the primary constructor. At runtime, instances of the inline class will be represented using this single property. </span><span style="background-color: white; color: #19191c; text-align: left;">This is the main feature of inline classes, which inspired the name </span><em class="article__em" id="bda856e6" style="background-color: white; border: 0px; color: #19191c; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;">inline</em><span style="background-color: white; color: #19191c; text-align: left;">: data of the class is </span><em class="article__em" id="c50362e6" style="background-color: white; border: 0px; color: #19191c; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;">inlined</em><span style="background-color: white; color: #19191c; text-align: left;"> into its usages (similar to how the content of <i>inlined functions</i> </span><span style="background-color: white; color: #19191c; text-align: left;">is inlined to call sites). All this is shown in the next example:</span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span style="background-color: white; color: #19191c; text-align: left;"><br /></span></span></div><div style="text-align: justify;"><span style="background-color: white; text-align: left;"><span style="color: #19191c;"><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;">@JvmInline</span></div><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;">value class LastName(val lastName: String)</span></div><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;"><br /></span></div><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;">// No actual instantiation of class LastName happens</span></div><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;">// At runtime surname contains just a String</span></div><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;">val surname = LastName("Barclay")</span></div><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;"><br /></span></div><div style="text-align: left;"><span style="font-family: arial; font-size: x-small;">assertEquals("Barclay", surname.lastName)</span></div><div style="text-align: left;"><br /></div><div style="text-align: justify;">If a class has two or more simple properties used directly in the class declaration then it can lead to problems as shown in the following example:</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: String, val firstName: String)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">val me = Name("BARCLAY", "Ken")</span></div><div><span style="font-family: arial; font-size: x-small;">val doppelganger = Name("Ken", "Barclay")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals(true, me.firstName == doppelganger.lastName)</span></div></div><div style="text-align: left;"><br /></div><div style="text-align: justify;">We simply cannot avoid inadvertently mixing the two properties. First, we introduce wrapper classes as shown earlier. Observe how the final comment line would produce a compilation error when we mix the first and last names.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="font-family: arial; font-size: x-small;">data class LastName(val lastName: String)</span></div><div><span style="font-family: arial; font-size: x-small;">data class FirstName(val firstName: String)</span></div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">val me = Name(LastName("BARCLAY"), FirstName("Ken"))</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals("Ken", me.firstName.firstName)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">// compilation error: type mismatch</span></div><div><span style="font-family: arial; font-size: x-small;">// val doppelganger = Name(FirstName("Ken"), LastName("BARCLAY"))</span></div></div><div style="text-align: left;"><br /></div><div style="text-align: left;">Then we remove the overhead of using simple types without loss of type-safety:</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="font-family: arial; font-size: x-small;">@JvmInline</span></div><div><span style="font-family: arial; font-size: x-small;">value class LastName(val lastName: String)</span></div><div><span style="font-family: arial; font-size: x-small;">@JvmInline</span></div><div><span style="font-family: arial; font-size: x-small;">value class FirstName(val firstName: String)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">data class Name(val lastName: LastName, val firstName: FirstName)</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">// No actual instantiation of class LastName happens</span></div><div><span style="font-family: arial; font-size: x-small;">// At runtime surname contains just a String</span></div><div><span style="font-family: arial; font-size: x-small;">val surname = LastName("BARCLAY")</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">val me = Name(surname, FirstName("Ken"))</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">assertEquals("Ken", me.firstName.firstName)</span></div></div><div style="text-align: left;"><br /></div><div style="text-align: justify;">Almost always simple types are constrained in some way, such as having to be in a certain range or match a certain pattern. It is very unusual to have an unbound <b>Int </b>or <b>String </b>in a real-world domain. In the next blog we will discuss how to enforce these constraints.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><br /></div><div><br /></div><div><div style="color: black; text-align: justify;">The code for the Dogs library can be found at:</div><div style="color: black; text-align: justify;"><br /></div><span style="color: black;"><div style="text-align: justify;">https://github.com/KenBarclay/TBA</div></span><span style="color: black;"><div style="text-align: justify;">https://github.com/KenBarclay/TBA</div></span></div><div><br /></div></div><div style="text-align: left;"><br /></div></span></span></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-18626019874208839922022-03-27T03:34:00.002-07:002022-11-15T07:43:47.556-08:00Kotlin: Map type<div style="text-align: left;"><span style="font-family: arial; font-size: large;"><b> Kotlin: Map type</b></span></div><div style="text-align: left;"><br /></div><div style="text-align: justify;"><span style="font-family: inherit;"><i>A map is an unordered collection of
key/value pairs. Inserting into a map requires two values: the key and the
corresponding value. Indexing the map with that same key retrieves the
associated value. The usual operations for a map include an operation to add a
new key/value pair, an operation to delete a key/value pair given the key, and
an operation to determine if the key is present in the map.</i></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><i><br /></i></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><i>The Dogs library supports two types of maps: the immutable and persistent Map implemented as a binary search tree; and the immutable and persistent Map based on a hash-array mapped trie. We will discus both in this blog.</i></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Maps</b></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">A <b>Map </b>is a collection of key-value pairs. It is sometimes known as a <i>dictionary </i>or an <i>association list</i>. The keys in a <b>Map </b>are unique and each key is associated with a value that need not be unique. The <b>Map </b>data type has two type parameters, for the key type and for the value type. So a Map<String, Int> maps <b>String</b>s to <b>Int</b>s, while a Map<Int, List<String>> maps an <b>Int </b>to a <b>List</b> of <b>String</b>s.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">The
usual operations for a <b>Map </b>include an operation to add a new key/value pair, an
operation to delete a key/value pair given the key, and an operation to
determine if the key is present in the <b>Map</b>. </span><span style="text-align: left;"><span style="font-family: inherit;">There
is no significance to the order in which the elements are added to the <b>Map</b>. </span></span><span style="font-family: inherit;">The <b>Map </b>data type is realized as a <i>balanced binary search tree</i>. </span><span style="text-align: left;"><span style="font-family: inherit;">Of
course, a balanced binary tree implies an ordering of the elements but this
will be invisible to the user. </span></span>The key type must be <b>Comparable </b>so that the ordering can be maintained.</div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Immutable and Persistent Maps</b></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span>Like the other data types in the Dogs library, <b>Map</b>s are immutable and persistent. </span><span style="background-color: white; text-align: left;"><span style="font-family: inherit;">Immutable <b>Map</b>s have many advantages over their mutable siblings. They are thread-safe and can be passed to untrusted libraries without any side effects. </span></span><span style="background-color: white; color: #273239; letter-spacing: 0.162px; text-align: left;"><span style="font-family: inherit;">A persistent <b>Map</b>, like a persistent <b>List</b>, is a data structure that always preserves the previous version of itself when it is modified. It does so by sharing parts of its structure.</span></span></div><div style="text-align: justify;"><span style="background-color: white; color: #273239; letter-spacing: 0.162px; text-align: left;"><span style="font-family: inherit;"><br /></span></span></div><div style="text-align: justify;"><span style="font-family: inherit;">The following figure shows the effect of inserting the key value <b>Kim</b> into the balanced binary tree <b>xs</b>
forming the new tree <b>ys</b>. The
resulting tree is no longer balanced since the subtree rooted at <b>Ken</b> has a depth of two for its right
subtree and a depth of zero for its left subtree. A rebalancing is achieved by
a rotation around the node labelled <b>Ken</b>.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiBZIEG1S4B52e_ayfsYfxu8v_fbzh5ddjWjqGb5t4okBA4mx0KSgQOELv_h5hFmCWWbfeaMUY-9q03-zMGRwcvF1spJ3YKjM6g4WUD0LtS1ibO5mOSPxqE6e4Sv6sBy7fNYlRnotsk50s6DSnC2oNwfGfDD6WaHpwvBtIxBs5UGWZ0PylHrTgQ_l4a" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="250" data-original-width="555" height="288" src="https://blogger.googleusercontent.com/img/a/AVvXsEiBZIEG1S4B52e_ayfsYfxu8v_fbzh5ddjWjqGb5t4okBA4mx0KSgQOELv_h5hFmCWWbfeaMUY-9q03-zMGRwcvF1spJ3YKjM6g4WUD0LtS1ibO5mOSPxqE6e4Sv6sBy7fNYlRnotsk50s6DSnC2oNwfGfDD6WaHpwvBtIxBs5UGWZ0PylHrTgQ_l4a=w640-h288" width="640" /></a></div><br /></span><p class="MsoBodyText"><span style="font-family: inherit;">The next figure illustrates a typical balanced insertion. Since the insertion into <b>xs</b> will first apply to the right
subtreee of the root node labelled <b>John</b>
then the left subtree of <b>John</b> can be
shared with the new tree <b>ys</b>.
Inserting key <b>Kim</b> into the subtree
labelled <b>Ken</b> will cause the
rebalancing and this new tree structure becomes part of the new tree <b>ys</b>.</span><span style="font-family: Comic Sans MS;"><o:p></o:p></span></p><p class="MsoBodyText"><span style="font-family: inherit;"><br /></span></p><p class="MsoBodyText"><span style="font-family: inherit;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgr_ao1elSndzfSBjBuh7jqlaFGPOEz0g7WxZOH_GdF_6mqYOmkOx7KFeYdX_oywxe057L8iS8_vY7ZGKdS7Suh_sXhA8zkHnT7uRu-7nziYQfp-R2sK6vtp-oSbVMgeGFH8SdFQErNufHHvV8XuDzoX4s_cnQw0535vPQ0lcMkdtg7HJpoqtMqy2jf" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="690" data-original-width="395" height="640" src="https://blogger.googleusercontent.com/img/a/AVvXsEgr_ao1elSndzfSBjBuh7jqlaFGPOEz0g7WxZOH_GdF_6mqYOmkOx7KFeYdX_oywxe057L8iS8_vY7ZGKdS7Suh_sXhA8zkHnT7uRu-7nziYQfp-R2sK6vtp-oSbVMgeGFH8SdFQErNufHHvV8XuDzoX4s_cnQw0535vPQ0lcMkdtg7HJpoqtMqy2jf=w366-h640" width="366" /></a></span></div><span style="font-family: inherit;"><br /><br /></span><p></p></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Working with Immutable Maps</b></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;">The following example demonstrates how to construct a <b>Map </b>and then perform the operations <b>containsKey </b>and <b>lookUpKey</b>. The <b>Map</b> values are the name of the states in the USA and uses their abbreviation for the key.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val states: Map<String, String> = MapF.of(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "AL" to "Alabama",</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "AZ" to "Arizona",</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "CA" to "California",</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "FL" to "Florida",</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "KS" to "Kansas",</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "NV" to "Nevada",</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "SC" to "South Carolina",</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "TX" to "Texas"</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(true, states.containsKey("FL"))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(false, states.containsKey("WY"))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(OptionF.some("California"), states.lookUpKey("CA"))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(OptionF.none(), states.lookUpKey("UT"))</span></div></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">In the next example the <b>Map </b>pairs the name of a color with its hexadecimal code:</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><div>val colors: Map<String, String> =</div><div> MapF.empty<String, String>()</div><div> .insert("Red" to "#FF0000")</div><div> .insert("Blue" to "#0000FF")</div><div> .insert("DarkBlue" to "#00008B")</div><div> .insert("Yellow" to "#FFFF00")</div><div> .insert("White" to "#FFFFFF")</div><div><br /></div><div>assertEquals(true, colors.containsKey("White"))</div><div>assertEquals(OptionF.some("#FFFF00"), colors.lookUpKey("Yellow"))</div><div>assertEquals(OptionF.none(), colors.lookUpKey("Green"))</div></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">In the following example the <b>Map</b> has a <b>String </b>for the key and an <b>Int</b> for the corresponding value. The code demonstrates the effect of inserting a new key/value pair into an existing <b>Map</b>. </span><span style="background-color: white; text-align: left;"><span style="font-family: inherit;">If the key is already present in </span></span><span style="background-color: white; font-family: inherit; text-align: left;">the <b>Map</b>, then the value is replaced.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><div>val people: Map<String, Int> = MapF.of(</div><div> "Ken" to 25,</div><div> "John" to 31,</div><div> "Jessie" to 22,</div><div> "Andrew" to 35,</div><div> "Gordon" to 35</div><div>)</div><div>val updated: Map<String, Int> = people.insert("Andrew" to 40)</div><div><br /></div><div>assertEquals(OptionF.some(22), people.lookUpKey("Jessie"))</div><div>assertEquals(OptionF.some(22), updated.lookUpKey("Jessie"))</div><div><br /></div><div>assertEquals(OptionF.some(35), people.lookUpKey("Andrew"))</div><div>assertEquals(OptionF.some(40), updated.lookUpKey("Andrew"))</div></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In the next example we show the effect of the member function <b>delete</b>. When the key is not a member of the <b>Map </b>then the original <b>Map</b> is returned.</div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><div>val people: Map<String, Int> = MapF.of(</div><div> "Ken" to 25,</div><div> "John" to 31,</div><div> "Jessie" to 22,</div><div> "Andrew" to 35,</div><div> "Gordon" to 35</div><div>)</div><div>val removed: Map<String, Int> = people.delete("Ken").delete("John")</div><div><br /></div><div>assertEquals(true, people.containsKey("Ken"))</div><div>assertEquals(false, removed.containsKey("Ken"))</div><div><br /></div><div>assertEquals(OptionF.some(22), people.lookUpKey("Jessie"))</div><div>assertEquals(OptionF.some(22), removed.lookUpKey("Jessie"))</div></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">In Dogs we implemented the data structures <b>List </b>and <b>Stream</b>, both of which could be folded. When writing code that needs to process data contained in one of these structures, we often do not care about the shape of the structure. Folding is one such operation that can be applied to them. We can fold over the values of a <b>Map </b>with the following example:</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><div>val people: Map<String, Int> = MapF.of(</div><div> "Ken" to 25,</div><div> "John" to 31,</div><div> "Jessie" to 22,</div><div> "Andrew" to 35,</div><div> "Gordon" to 35</div><div>)</div><div><br /></div><div>assertEquals(148, people.foldLeft(0){acc -> {age -> acc + age}})</div><div>assertEquals(0, MapF.empty<String, Int>().foldLeft(0){acc -> {age -> acc + age}})</div></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Hash-Array Mapped Tries</b></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">The
prime candidate data structure for efficient <b>Map </b>collections is the
<i>Hash-Array Mapped Trie</i> (HAMT) by Bagwell. A general trie is a lookup structure
for finite strings that acts like a deterministic finite automaton. In a HAMT,
the strings are the bits of the hash codes of the elements stored in the trie.
Depending on the branching factor we may use different sizes of chunks from the
hash code for indexing into the (sparse) array of child nodes.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">Figures (a), (b) and (c) graphically illustrate the structure of a small HAMT collection
with branching factor 32 after step-by-step inserting the objects A, B, C, and
D. HAMTs encode the hash codes of the elements in their tree structure (cf. (d)).
The prefix tree structure grows lazily upon insertion until the new element can
be distinguished unambiguously from all other elements by its hash code prefix.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhNjrIk7vImQjdiw5fENG8NleRZzN6SGdmeVQpiat49C04--p46vKMvLk6vz5NNxBjuP8n_OQknXO41qZzyNm_T_eud7Qc-g0_OpNFuw7Rnf6I2GrStp4jci4evSjMwddCrLupsDLAkm0dSLNWc4N-HSuEQXnSjRbsyR8QhMrLgVy6PD2cT1r1o79aL" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="230" data-original-width="555" height="266" src="https://blogger.googleusercontent.com/img/a/AVvXsEhNjrIk7vImQjdiw5fENG8NleRZzN6SGdmeVQpiat49C04--p46vKMvLk6vz5NNxBjuP8n_OQknXO41qZzyNm_T_eud7Qc-g0_OpNFuw7Rnf6I2GrStp4jci4evSjMwddCrLupsDLAkm0dSLNWc4N-HSuEQXnSjRbsyR8QhMrLgVy6PD2cT1r1o79aL=w640-h266" width="640" /></a></div><br /></span><span style="font-family: inherit;">The
index numbers in the left top corner of each node refer to the positions of
elements in an imaginary sparse array. This array is actually implemented as a
32-bit bitmap and a completely filled array with length equal to the node’s
arity.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">Immutable
HAMTs perform path-copying on updates: the edited node and all its parent nodes
are reallocated. The resulting new root node satisfies the immutability
property by resembling the updated path-copied branch and, for the remainder,
references to unmodified branches.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">The Dogs implementation of an HAMT has an interface similar to that of the <b>Map </b>shown in the examples above. It includes, for example, the operations <b>containsKey</b>, <b>lookUpKey</b>, <b>insert </b>and <b>foldLeft</b>.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">A </span><span style="background-color: white; color: #292929; letter-spacing: -0.06px; text-align: left;"><span style="font-family: inherit;"><b>Map </b>is an object that maps keys to values. A <b>Map </b>cannot contain duplicate keys; each key can map to at most one value. However, we come across scenarios wherein more than one value has to be mapped to a key. In such scenarios where multiple values need to be mapped to a single key, we end up creating a <b>Map </b>with a single key but a collection of values: the <b>MultiMap</b>.</span></span></div><div style="text-align: justify;"><span style="background-color: white; color: #292929; letter-spacing: -0.06px; text-align: left;"><span style="font-family: inherit;"><br /></span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span style="background-color: white; color: #202122; text-align: start;">The </span><b style="background-color: white; color: #202122; text-align: start;">Dewey Decimal Classification</b><span style="background-color: white; color: #202122; text-align: start;"> (</span><b style="background-color: white; color: #202122; text-align: start;">DDC</b><span style="background-color: white; color: #202122; text-align: start;">), colloquially known as </span><b style="background-color: white; color: #202122; text-align: start;">Dewey Decimal System</b><span style="background-color: white; color: #202122; text-align: start;">, is a proprietary </span><a href="https://en.wikipedia.org/wiki/Library_classification" style="background: none rgb(255, 255, 255); text-align: start; text-decoration-line: none;" title="Library classification"><span style="color: black;">library classification</span></a><span style="background-color: white; color: #202122; text-align: start;"> system which allows new books to be added to a library in their appropriate location based on subject.</span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">We define a library catalog based on the Dewey classification with the </span><span style="font-family: inherit;"><b>Book </b>class and a typealias for a <b>MultiMap </b>with the Dewey code for the key and a <b>List </b>of <b>Book</b>s associated with that classification:</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">data class Book(val isbn: String, val title: String, val author: String)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">typealias Dewey = Map<String, List<Book>></span></div><div style="font-family: inherit;"><br /></div><div style="font-family: inherit;">Using the HAMT <b>Map </b>we associate a collection of <b>Book</b>s with the Dewey classification. In the following listing the first assert determines the number of algebra books, while the second assert finds how many books are authored by Saumont in the programming category:</div><div style="font-family: inherit;"><br /></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val dewey: Dewey = MapF.of(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "005" to ListF.of( // Programming</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Book("9781617295362", "The Joy of Kotlin", "Pierre-Yves Saumont"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Book("9781617293290", "Kotlin in Action", "Dmitry Jemerov"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Book("9781530075614", "Kotlin for Android Developers", "Antonio Leiva"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Book("9781617292736", "Functional Programming in Java", "Pierre-Yves Saumont")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "512" to ListF.of( // Algebra</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Book("9789083136608", "Linear Algebra", "Michael Cohen"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Book("9780471433347", "Abstract Algebra", "David Dummit")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> "520" to ListF.of( // Astronomy</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Book("9780008389321", "The Universe", "Andrew Cohen")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> )</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(2, dewey["512"].size()) // number of algebra books</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(2, dewey["005"].filter{book -> (book.author == "Pierre-Yves Saumont")}.size())</span></div></div><div style="font-family: inherit;"><br /></div></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><b>Performance</b></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><div>A benchmark comparing our immutable persistent <b>Map</b>, immutable persistent HAMT <b>Map</b>, Kotlin's mutable <b>MutableMap </b>and the <b>PersistentMap </b>class from the Immutable Collections Library for Kotlin at [https://github.com/Kotlin/kotlinx.collections.immutable]. The timings measure (in ms) inserting 10000 elements into the collections:</div><div style="text-align: left;"><br /></div><div style="text-align: left;">Insert 10000 elements into our immutable/persistent <b>Map</b>:<span> 9.2</span></div><div style="text-align: left;">Insert 10000 elements into our immutable/persistent HAMT <b>Map</b>:<span> 8.2</span></div><div style="text-align: left;">Insert 10000 elements into Kotlin's <b>MutableMap </b>type:<span> </span>1.1</div><div style="text-align: left;">Insert 10000 elements into kotlinx <b>PersistentMap </b>type:<span> </span><span> 14.6</span></div></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">A second benchmark compares looking up the values for these 10000 keys in our immutable persistent <b>Map</b>, immutable persistent HAMT <b>Map</b>, Kotlin's mutable <b>MutableMap </b>and the <b>PersistentMap </b>class from the Immutable Collections Library for Kotlin at [https://github.com/Kotlin/kotlinx.collections.immutable]. The timings measure (in ms) searching 10000 elements in the collections:</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><div style="text-align: left;">Lookup 10000 elements in our immutable/persistent <b>Map</b>:<span> 324.8</span></div><div style="text-align: left;"><span style="font-family: inherit;">Lookup</span><span style="font-family: inherit;"> </span>10000 elements in our immutable/persistent HAMT <b>Map</b>:<span> 3.1</span></div><div style="text-align: left;"><span style="font-family: inherit;">Lookup</span><span style="font-family: inherit;"> </span>10000 elements in Kotlin's <b>MutableMap </b>type:<span> </span>1.4</div><div style="text-align: left;"><span style="font-family: inherit;">Lookup</span><span style="font-family: inherit;"> </span>10000 elements in kotlinx <b>PersistentMap </b>type:<span> </span><span> 3.9</span></div></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;"><br /></span></div></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: left;"><br /></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-30753257083629460892022-03-25T08:39:00.001-07:002022-11-15T07:50:43.441-08:00Kotlin: Vector type<div style="text-align: left;"><span style="font-family: arial; font-size: large;"><b> Kotlin: Vector type</b></span></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><i>xxxxx</i></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;">Here we describe
the <i>persistent vector</i> attributed to Rich Hickey and influenced by Phil
Bagwell’s Ideal Hash Trees. The persistent vector gives practically constant
time for lookup operations, append and update operations; significantly better
than that for our persistent lists.<o:p></o:p></span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;">Such
vectors are sometimes known as <i>bitmapped
vector tries</i>. Tries are specialized trees in which all the data is stored
in its leaves. Further, the internal nodes of a trie have more than the two
branches used in balanced binary search trees. In this implementation each
node has 32 branches producing a very shallow tree structure. A lookup
operation uses parts of the key to select the correct branch.</span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;">A vector uses
the <i>index </i>as the key for lookup and other operations. We must split up the
index in some way to traverse the branches of the trie. One simple scheme uses <i>digit
partitioning</i>, splitting a key into its individual digits. However, this
approach requires integer division and integer modulo operations which are too
time-consuming.</span><span style="font-family: Comic Sans MS;"><o:p></o:p></span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;"><i>Bit partitioned tries</i> are a subset of
digit partitioned tries. Conceptually they operate the same way as digit
partitioned tries. Instead of splitting the key into digits, we split it into
chunks of 5 bits for our 32-way branching. The expensive integer arithmetic is
replaced with more efficient bit shift and logical and operations.</span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;">To
illustrate, consider that we have 2 bit partitioning/4-way branching as shown
in the following figure. To look up a value in a trie with up to 1024 elements, the root
of the tree is a pointer to a size-4 array with each element a pointer to
similar sub-nodes. The lowest level node will have pointers to the actual data
values.</span></p><p class="MsoBodyText" style="text-align: justify;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgDD7ndv-nAFXeGoJdE6uvxSCBoKnhzHqPNbNIpMhSrvaj2aNgIAGxQw8I-d3CnX4P_nv1-Q6i61vy-MQ8S0WX1B_qhcIlHj0Z6NN4BezjVDkXV70mpGDZuheKVMHtWWL_jp2BQwwKXYy3YmlzzgrsYg8qAls0lI__hZ5jaSL9ZAyF9Rw-iSU3h61wX" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="285" data-original-width="554" height="330" src="https://blogger.googleusercontent.com/img/a/AVvXsEgDD7ndv-nAFXeGoJdE6uvxSCBoKnhzHqPNbNIpMhSrvaj2aNgIAGxQw8I-d3CnX4P_nv1-Q6i61vy-MQ8S0WX1B_qhcIlHj0Z6NN4BezjVDkXV70mpGDZuheKVMHtWWL_jp2BQwwKXYy3YmlzzgrsYg8qAls0lI__hZ5jaSL9ZAyF9Rw-iSU3h61wX=w640-h330" width="640" /></a></div><br /><div style="text-align: justify;"><span style="font-family: inherit;">We
interpret an index as divided into chunks of 2 bits. Hence the decimal index
637 has the binary representation 10-01-11-11-01. The chunks are mapped to
levels in the tree. Fetching the element at index 637 involves indexing the
root node at binary 10 to obtain the node at the next level. This node is then
indexed at binary 01 to obtain the node at level 3, and so on. In general the
cost of performing a lookup is proportional to the height of the tree. In the
32-way branching implementation the tree has a very wide and shallow structure producing
constant time lookup or, more precisely, O(log</span><sub style="font-family: inherit;">32</sub><span style="font-family: inherit;"> n) where n is the
number of elements. Tries with at most 6 levels are capable of referring to one
billion elements.</span></div><p></p><div style="text-align: justify;"><span style="font-family: inherit;">The following example illustrates defining a number of extension functions on specialized
vectors. Extension function <b>maximum</b>
finds the greatest value in the vector. Extension function <b>multiply</b> creates a new vector comprising the product of each of the
original values and the given scalar. Extension function <b>manhattan</b> computes the distance between two equal-sized vectors
based on a strictly horizontal and/or vertical path.</span></div><div style="text-align: justify;"><span style="font-family: "Comic Sans MS"; font-size: 10pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: AR-SA;"><br /></span></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun Vector<Double>.maximum(): Double =</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> this.foldLeft(this[0]){max, d -> Math.max(max, d)}</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun Vector<Double>.multiply(scalar: Double): Vector<Double> =</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> this.map{d -> scalar * d}</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun Vector<Double>.manhattanNorm(vec: Vector<Double>): Double {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return if (this.size() != vec.size())</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> throw IllegalArgumentException("manhattanDistance: vectors differ in size")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> else {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> var sum: Double = 0.0</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val size: Int = this.size()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> for (index in (0 until size)) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val dist: Double = this[index] - vec[index]</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> sum += abs(dist)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> sum</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // manhattanNorm</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val vec1: Vector<Double> = VectorF.of(1.0, 2.0, 3.0, 4.0, 5.0)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val vec2: Vector<Double> = VectorF.of(1.0, -2.0, 4.0, 7.0, 9.0)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(5.0, vec1.maximum())</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(VectorF.of(2.0, 4.0, 6.0, 8.0, 10.0), vec1.multiply(2.0))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(12.0, vec1.manhattanNorm(vec2))</span></div><div><span style="font-family: Comic Sans MS;"><span style="font-size: 13.3333px;"><br /></span></span></div><div><span style="font-family: inherit; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: AR-SA;">The next example declares a simple matrix class in which its elements are stored in column
major order using our vector class. Note the <b>init</b> block to check the dimensions and the support function <b>makeVector</b> to create a vector of some
given size and a function for delivering the values.</span></div><div><span style="font-family: "Comic Sans MS"; font-size: 10pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: AR-SA;"><br /></span></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">class MatrixException(message: String) : Exception(message)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">class Matrix(val rows: Int, val columns: Int, val storage: Vector<Double>) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> constructor(rows: Int, columns: Int, value: Double = 0.0): this(rows, columns, VectorF.replicate(rows * columns, value))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> constructor(rows: Int, columns: Int, f: (Int, Int) -> Double): this(rows, columns, makeVector(rows, columns, f))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> operator fun get(row: Int, col: Int): Double {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> if (row < 0 || row >= rows)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> throw MatrixException("get: incorrect row index")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> if (col < 0 || col >= columns)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> throw MatrixException("get: incorrect column index")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return storage[rows * col + row]</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fun makeVector(rows: Int, columns: Int, f: (Int, Int) -> Double): Vector<Double> {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> var vec: Vector<Double> = VectorF.empty()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> for (col in 1..columns) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> for (row in 1..rows)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> vec = vec.append(f(row, col))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return vec</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // companion object</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> init {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> if (storage.size() != rows * columns)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> throw MatrixException("incorrect sizes")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // init</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // Matrix</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> // Create the matrix ((1.0, 2.0), (3.0, 4.0), (5.0, 6.0))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val mat1: Matrix = Matrix(3, 2, VectorF.of(1.0, 3.0, 5.0, 2.0, 4.0, 6.0))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> // Create the matrix ((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val mat2: Matrix = Matrix(3, 3){row, col -> if (row == col) 1.0 else 0.0}</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(2.0, mat1[0, 1])</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(6.0, mat1[2, 1])</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(1.0, mat2[2, 2])</span></div></div><div><br /></div><div><div><br /></div><div><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;"><br /></span></div></div></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-12167071211425568472022-03-25T08:28:00.033-07:002022-11-04T06:24:45.097-07:00Dogs<p> <b style="font-family: arial; font-size: x-large;">Dogs: A library of immutable and persistent data types</b></p><div style="text-align: justify;"><span style="font-family: inherit;"><span><i><b>Dogs </b>is a Kotlin library of immutable and persistent data types such as the <b>List </b>type or the <b>MultiMap</b> type. Through Kotlin we provide statically type safe functional data structures that are inspired by Haskell's data types.</i></span></span></div><div style="text-align: left;"><span style="font-family: inherit;"><span><br /></span></span></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="font-family: inherit;"><span><br /></span></span></div><div style="text-align: left;"><span><span style="font-family: arial;"><b>Motivation</b></span></span></div><div style="text-align: left;"><span style="font-family: inherit;"><span><br /></span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span>A data structure is a way of storing and organizing data so that it can be used efficiently. Different kinds of data structures are suited to different applications. For example, compilers usually employ <i>hash tables</i> to manage information about program identifiers.</span></span></div><div style="text-align: left;"><span style="font-family: inherit;"><span><br /></span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span>Ordinary data structures, such as those provided through Kotlin, are <i>ephemeral</i> in the sense that making a change to the structure destroys the old version, leaving only the new one. This is the case for the Java/Kotlin <b>List</b>, <b>Set </b>and <b>Map </b>types. These <i>imperative data structures</i> operate through in-place mutation of data - the data structure is <i>mutable</i>. In our everyday usage of Kotlin data structures, we mutate lists, maps, sets and other types to realize the algorithm that we implement.</span></span></div><div style="text-align: justify;"><br /></div><div style="text-align: left;"><div style="text-align: justify;"><span style="font-family: inherit;">An important property of <i>functional data structures</i> is that they always <i>persist </i>- updating a functional data structure does not destroy the existing version, but rather creates a new version that coexists with the old version. Persistence is achieved by copying the affected nodes of a data structure and making all changes in the copy rather than the original. Because they are never modified directly, all nodes that are unaffected by an update can be shared between the old and the new versions of the structure without worrying that a change in one version will inadvertently be visible to the other.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">Despite their name, persistent data structures do not refer to data structures stored on disk. Instead they are immutable data structures which are copy-on-write. That is, whenever you mutate a persistent data structure a new one is created that contains the data in the original plus the mutation while the original is left untouched. To make this reasonably efficient, <i>structural sharing</i> is used between the data structures.</span></div><div style="text-align: justify;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;">Functional languages exploit immutable and persistent data structures, many of them based on the seminal book by Chris Okasaki, <a href="http://www.cambridge.org/catalogue/catalogue.asp?isbn=0521663504" target="_blank">Purely Functional Data Structures</a>.</span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Organisation</b></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">A data structure in <b>Dogs </b>is defined over three Kotlin source files. For example, the immutable and persistent <b>List </b>data structure is defined in the source files List.kt, ListE.kt and ListF.kt. The class declaration is defined in the source file List.kt. Contravariant functions which would otherwise conflict with the covariant type parameter in the <b>List </b>class appear as extension functions in the source file ListE.kt. The object declaration <b>ListF</b> from the file ListF.kt is used to present functions that deliver a <b>List </b>but are not natural members of the <b>List </b>class.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Never null</b></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Kotlin treats <b>null</b> in a special way so that we may work safely with values that might be <b>null</b>. For instance, the null-safe operator for accessing properties foo?.bar?.baz will not throw an exception if either <b>foo</b> or its <b>bar</b> property is <b>null</b>, instead directly returning <b>null</b>.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Another approach to this problem is to provide a type for representing optional values. Values that may be present or absent are supported by the <span style="mso-bidi-font-weight: normal;">Option<A></span> class from the <b>Dogs </b>library. Thus, for example, a function to <b>open </b>an <b>Account</b> in a personal banking domain might be:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun open(accNo: String, accName: String, initDeposit: Int): Option<Account></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">returning an Option<Account> rather than an <b>Account</b>. When we return Option<Account> we are returning an abstraction over the evaluation. The caller of function <b>open </b>can decide whether to extract the value out of it or compose it with other abstractions.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b>Option </b>as an abstraction follows other abstractions in the <b>Dogs </b>library. Like a <b>List</b> it can be mapped over; it is <i>foldable</i> and can be collapsed into a single value; it follows the <i>monadic </i>model of computation in which we can chain a sequence of the above function invocations.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The <b>Dogs </b>library supports migrating from using <b>null </b>to adopting <b>Option</b>. The generic types in <b>Dogs </b>have <b>Any </b>as their explicit upper bounds. Without this, Kotlin considers <b>Any?</b> as the default upper bounds and would allow <b>null</b> types as members. Thus, the <b>Option</b> and <b>List </b>classes appear as:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">class Option<A : Any> ...</span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">class List<A: Any> ...</span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Testing</b></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">An extensive collection of unit tests are provided by the separate IntelliJ project <b>DogsTests</b>. The project contains a number of class files that provide the unit tests for the <b>Dogs </b>classes. For example, the file <b>OptionTests </b>carries the unit tests for the <b>Option </b>class.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The IntelliJ project <b>DogsPBTests </b>is a collection of <i>property-based tests</i> for some of the fundamental laws that apply to the <b>Dogs </b>classes. These property-based tests are conducted by the <b>KwikCheck </b>framework. <b><a href="https://kenbarclay.blogspot.com/2020/05/kotlin-property-based-testing.html" target="_blank">KwikCheck</a></b><b> </b>is a property-based testing framework written entirely in Kotlin and build atop the <b>Dogs</b> library.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Documentation</b></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The following series of blogs present a user description of some of the data structures included in <b>Dogs</b>. The Function type article describes Kotlin functions especially those features used across the library, such as <i>curried functions, function composition </i>or <i>partial function application</i>.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><a href="https://kenbarclay.blogspot.com/2020/05/kotlin-function-type.html" target="_blank">Function type</a></div><div style="text-align: justify;"><a href="https://kenbarclay.blogspot.com/2020/05/kotlin-option-type.html" target="_blank">Option type</a></div><div style="text-align: justify;"><a href="https://kenbarclay.blogspot.com/2020/07/kotlin-either-type.html" target="_blank">Either type</a></div><div style="text-align: justify;"><a href="https://kenbarclay.blogspot.com/2020/06/kotlin-validation-type.html" target="_blank">Validation type</a></div><div style="text-align: justify;"><span color="rgba(0, 0, 0, 0.52)" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif" style="background-color: white; font-size: 14px; text-align: left;"><a href="https://kenbarclay.blogspot.com/2020/06/kotlin-list-type.html" target="_blank">List type</a></span></div><div style="text-align: justify;"><span color="rgba(0, 0, 0, 0.52)" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif" style="background-color: white; font-size: 14px; text-align: left;"><a href="https://kenbarclay.blogspot.com/2020/06/kotlin-non-empty-list-type.html" target="_blank">Non Empty List type</a></span></div><div style="text-align: justify;"><span style="background-color: white; font-size: 14px; text-align: left;"><a href="https://kenbarclay.blogspot.com/2022/03/kotlin-stream-type.html" target="_blank">Stream type</a></span></div><div style="text-align: justify;"><span color="rgba(0, 0, 0, 0.52)" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif" style="background-color: white; font-size: 14px; text-align: left;"><a href="https://kenbarclay.blogspot.com/2022/03/kotlin-map-type.html" target="_blank">Map type</a></span></div><div style="text-align: justify;"><span color="rgba(0, 0, 0, 0.52)" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif" style="background-color: white; font-size: 14px; text-align: left;"><a href="https://kenbarclay.blogspot.com/2022/03/kotlin-vector-type.html" target="_blank">Vector type</a></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><br /></div><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><br /></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-86648619443853715572022-03-16T08:41:00.002-07:002022-11-15T07:40:45.951-08:00Kotlin: Stream type<div style="text-align: left;"><span style="font-family: arial; font-size: large;"><b> Kotlin: Stream type</b></span></div><div style="text-align: left;"><p class="MsoBodyText" style="text-align: justify;"><i>The class <b>Stream </b>implements lazy lists where elements are only evaluated when </i><i>they are needed. A Stream is like a List, except that its elements are computed lazily, in a </i><i>manner similar to how a view creates a lazy version of a collection. Because </i><i>Stream elements are computed lazily, a Stream can be long ... infinitely long. </i><i>Other than this behavior, a Stream behaves similarly to a List.</i></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;"><br /></span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;"><br /></span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: arial;"><b>Motivation</b></span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;">A <i>stream</i>
is an ordered collection containing a possibly infinite number of elements.
Strange as it may seem an infinite sequence of values finds many uses in real
applications. Several phone applications, such as the mail app, use
lists of indefinite length. A social media application page loads the first several
pages of updates then lets the user load more.</span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;">A
stream is sometimes referred to as a <i>lazy
list</i>. It informs us that the elements are evaluated lazily. In effect the
computation part is delayed until an element from the stream is requested. That
way we can defer expensive operations until they are actually required.</span></p><p class="MsoBodyText" style="text-align: justify;"><span style="font-family: inherit;">The
custom class <b>Stream</b> defines a lazy stream. It has a similar interface to
that of <b>List</b>, including the member
functions <b>take</b>, <b>map</b> and <b>foldLeft</b>. The <b>StreamF</b> object declaration has definitions for functions such as <b>from</b> (create a <b>Stream </b>from a source such as an immutable <b>List</b>) and <b>range</b> (create a <b>Stream </b>over a range of numeric values) that would not normally be member
functions. This simple example should need little explanation:</span></p></div><div style="text-align: left;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers10: Stream<Int> = StreamF.closedRange(1, 10)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(10, numbers10.size())</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(1, numbers10.head())</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(55, numbers10.foldLeft(0){acc -> {n -> acc + n}})</span></div></div><div style="text-align: left;"><br /></div><div style="text-align: left;">The member functions <b>take</b> and <b>drop</b> operate exactly as their <b>List </b>counterparts. Two simple examples are:</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers1000: Stream<Int> = StreamF.range(0, 1000)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(StreamF.of(0, 1, 2, 3, 4), numbers1000.take(5))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(StreamF.of(100, 101, 102, 103, 104), numbers1000.drop(100).take(5))</span></div><div><br /></div><div>We create a <b>Stream </b>of objects using the overloaded function <b>from </b>from the associated <b>StreamF </b>object declaration:</div><div><br /></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">data class Person(val name: String, val age: Int)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val people: List<Person> = ListF.of(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person("Ken", 25),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person("John", 31),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person("Jessie", 22)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val totalAges = StreamF.from(people).map{per -> per.age}.foldLeft(0){acc -> {age -> acc + age}}</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(78, totalAges)</span></div><div><br /></div><div style="text-align: justify;">We also have various <i>fold </i>operations on a <b>Stream</b>. Folding <b>Stream</b>s is somewhat different from folding <b>List</b>s. The primary difference is that <b>Stream</b>s are unevaluated. The function <b>foldRight </b>from the <b>List </b>class cannot be made stack safe and for large <b>List</b>s could overflow the stack. Similarly, the <b>Stream </b>class function <b>foldRight </b>will overflow the stack if, for example, it is adding the elements of a Stream<Int>:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers5: Stream<Int> = StreamF.of(1, 2, 3, 4, 5)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(15, numbers5.foldRight(0){n -> {acc -> acc + n}})</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers10000: Stream<Int> = StreamF.closedRange(1, 10000)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">numbers10000.foldRight(0){n -> {acc -> acc + n}} // stack overflow</span></div><div><br /></div><div>We cannot make <b>foldRight </b>stack safe. Notwithstanding, it has many interesting use-cases. In the following we implement the <b>map </b>function using <b>foldRight</b>:</div><div><br /></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun <A, B> map(stream: Stream<A>, f: (A) -> B): Stream<B> =</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> stream.foldRight(StreamF.empty()){a: A -></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> {sb: Stream<B> -></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> StreamF.cons(f(a), sb)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> StreamF.of(false, true, false, true, false),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> map(StreamF.closedRange(1, 5)){n: Int -> isEven(n)}</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><br /></div><div>It is possible to generate an infinite stream, i.e. a <b>Stream </b>of infinite length. <span style="font-family: inherit;">Function
<b>range</b> delivers a stream of integers
starting from its argument value, say 1. In effect it produces the stream 1,
2, 3, ..., lazily. In the following example the function <b>firstOddNumbers</b> finds an initial stream of odd numbers. It is implemented with the
functions <b>range</b>, <b>filter</b> and <b>take</b>.</span></div></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun firstOddNumbers(n: Int): Stream<Int> =</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> StreamF.range(1).filter{n -> isOdd(n)}.take(n)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers: Stream<Int> = StreamF.range(1)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(StreamF.of(1, 2, 3, 4, 5), numbers.take(5))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(StreamF.of(1, 3, 5, 7, 9), firstOddNumbers(5))</span></div></div><div><br /></div><div><span style="font-family: inherit;">A
positive integer greater than one is prime if it is divisible by itself and by
one. The <i>Sieve of Eratosthenes</i> is an
algorithm that works by cancelling out all the multiples of numbers, once they
are established as prime. The primes are the values that remain.</span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;">We
begin with a sequence of numbers starting with 2. The head element is 2 and is prime, and we
remove all the multiples of 2 from the sequence. The head of the remainder of
the sequence is 3 and is prime. We sieve the remainder of the sequence removing
all multiples of 3. The process is repeated indefinitely.</span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;">In
the next example function <b>sieve </b>is an
implementation for this algorithm using a lazy stream. The function accepts the
stream of integers [2, 3, 4, 5, ...] and converts it into a stream of primes
[2, 3, 5, ...], lazily. The head element of the input stream is the head of the
stream of primes. The tail of the primes is defined by the function literal. It
makes a recursive call on <b>sieve</b>
filtering out all the multiples from the tail of the input.</span></div><div><span style="font-family: inherit;"><br /></span></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun seive(numbers: Stream<Int>): Stream<Int> {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val head: Int = numbers.head()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return StreamF.cons(head, object: Product1<Stream<Int>>() {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> override fun first(): Stream<Int> =</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> seive(numbers.tailP().first().removeAll{n: Int -> (n % head == 0)})</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> })</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">}</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val primes: Stream<Int> = seive(StreamF.range(2))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val primes10: Stream<Int> = primes.take(10)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(StreamF.of(2, 3, 5, 7, 11, 13, 17, 19, 23, 29), primes10)</span></div><div><br /></div><div><span style="font-family: inherit;">Observe
how the stream with all the multiples removed is incorporated into the lazy
result. The tail of the result stream is not a stream itself, as happens with
the list, rather it is an instance of <b>Product1</b>
that wraps a single value representing the stream tail. The abstract class <b>Product1</b> requires a definition for the
accessor member function <b>first</b> used
to obtain the wrapped single value. Defining a <b>Product1</b> object where the result stream is required is how the
laziness is achieved.</span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: arial;"><b>Stream pipelines</b></span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;"><span style="background-color: white; text-align: left;">To perform a computation, stream </span><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps" style="background-color: white; text-align: left; text-decoration-line: none;"><span style="color: black;">operations</span></a><span style="background-color: white; text-align: left;"> are composed into a </span><em style="background-color: white; text-align: left;">stream pipeline</em><span style="background-color: white; text-align: left;">. A stream pipeline consists of a source (which might be an array, a collection, a generator function, an I/O channel, etc), zero or more </span><em style="background-color: white; text-align: left;">intermediate operations</em><span style="background-color: white; text-align: left;"> (which transform a stream into another stream, such as filter(predicate)</span><span style="background-color: white; text-align: left;">), and a </span><em style="background-color: white; text-align: left;">terminal operation</em><span style="background-color: white; text-align: left;"> (which produces a result or side-effect, such as <b>toList</b>)</span><span style="background-color: white; text-align: left;">. Streams are lazy; computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed. The earlier example with the <b>Person </b>class has <b>map </b>as an intermediate operation and <b>foldLeft </b>as the terminal operation.</span></span></div></div></div></div><div><br /></div></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="font-family: arial;"><b>Achieving Laziness</b></span></div><div style="text-align: left;"><br /></div><div style="text-align: justify;">The <b>Stream </b>type is similar to the singly linked list, <b>List</b>. The <b>Stream </b>type has some subtle and important differences. The starting point for our <b>Stream </b>data type is:</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="font-family: arial; font-size: x-small;">sealed class Stream<A> {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> class Nil<A>() : Stream<A>()</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> class Cons<A>(val hd: A, val tl: Product1<Stream<A>>) : Stream<A>()</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div><div><br /></div><div style="text-align: justify;">The <b>Cons </b>class has head (<b>hd</b>) and tail (<b>tl</b>) properties. Importantly, the tail property is an instance of the <b>Product1 </b>class that implements the laziness. The class is abstract and concrete implementations must define the abstract <b>first </b>member function. We saw this class in use with the <b>seive </b>function.</div><div><br /></div><div><div><span style="font-family: arial; font-size: x-small;">abstract class Product1<A> {</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;"> abstract fun first(): A</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">}</span></div><div><br /></div><div>The function <b>cons</b> (in the <b>StreamF </b>object declaration) is defined by:</div></div></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="font-family: arial; font-size: x-small;">fun <A> cons(a: A, stream: Stream<A>): Stream<A> {</span></div><div><span style="font-family: arial; font-size: x-small;"> return Cons(a, object : Product1<Stream<A>>() {</span></div><div><span style="font-family: arial; font-size: x-small;"> override fun first(): Stream<A> = stream</span></div><div><span style="font-family: arial; font-size: x-small;"> })</span></div><div><span style="font-family: arial; font-size: x-small;">} // cons</span></div><div><br /></div><div>where we lazily create, without evaluation, the tail part of the new <b>Stream</b>.</div></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="font-family: arial;"><b>Performance</b></span></div><div style="text-align: left;"><br /></div><div style="text-align: justify;"><b>Stream</b>s offer significant performance improvements over <b>List</b>s. In the following a <b>Stream </b>of 10000 integers 1, 2, 3, ..., 10000 is first filtered to take only the even-values, squaring the resulting values, filtering out those that are below 1000, then taking only the first 10.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">stream.filter{n -> isEven(n)}.map{n -> n * n}.filter{n -> (n < 1000)}.take(10)</span></div><div style="text-align: left;"><br /></div><div style="text-align: left;">In the next table we show the timings to filter/map/filter/take integers from various integer collections containing 1, 2, 3, ..., 10000. Our <b>Stream </b>is significantly faster than all others by not having to create intermediate structures.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div>filter/map/filter/take pipeline 10000 integers from our immutable/persistent <b>List</b>: 0.965</div><div>filter/map/filter/take pipeline 10000 integers from Kotlin's <b>MutableList</b> type: 0.464</div><div>filter/map/filter/take pipeline 10000 integers from Kotlin's <b>List</b> type: 0.461</div><div>filter/map/filter/take pipeline 10000 integers from kotlinx <b>PersistentList</b> type: 0.478</div><div>filter/map/filter/take pipeline 10000 integers from our <b>Stream</b>: 0.001</div></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The code for the Dogs library can be found at:</div><div style="text-align: justify;"><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;"><br /></span></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-68236446259645059842022-02-28T07:31:00.004-08:002022-11-04T07:53:10.428-07:00Kotlin: Validation type<span style="font-family: arial; font-size: large;"><b>Kotlin: Validation type</b></span><br />
<br />
<div style="text-align: justify;">
<span style="color: #515151;"><span style="background-color: white;"><i>Any system will have errors and how we handle them is important. Consistent and transparent error handling is critical to any production ready system. Here we explore the functional approach to error handling, developing techniques to capture errors elegantly without contaminating your code with ugly conditionals and try/catch clauses. We consider the <b>Validation </b>class </i></span></span><i>included in the custom library <b>Dogs</b>.</i></div>
<br />
<br />
<br />
<span style="font-family: arial;"><b>Motivation</b></span><br />
<br />
<div style="text-align: justify;">
Validation can be found in different forms when error(s) are detected. Validation can return immediately when the first error (or exception) has been encountered; the validation result may or may not contain the validation error or exception message. This scenario is called <i>fast failing</i> validation, in which the validation does not validate all the business rules and only zero or one message is returned, and the process shall be cut short upon first error. This simple form of validation is sometimes considered insufficient, as a full validation is not carried out with accumulated errors. See the <b>Either </b>type blog on fast failing.</div>
<br />
<div style="text-align: justify;">
Validating all the business rules, and accumulating errors, is very different from fast failing validation. <i>Applicative functors</i> are proposed, and they have effectively solved accumulation problems. The <b>Validation </b>data type has an instance of applicative that accumulates on the error side.</div>
<br />
<div style="text-align: justify;">
The <b>Validation</b> data type is isomorphic to Either. <b>Validation </b>is a container type with two type parameters: A Validation<E, A> instance can contain either an instance of <b>E</b>, or an instance of <b>A </b>(a disjoint type). Validation has exactly two sub types, <b>Failure</b> and <b>Success</b>. If a Validation<E, A> object contains an instance of <b>E</b>, then the <b>Validation</b> is a <b>Failure</b>. Otherwise it contains an instance of <b>A</b> and is a <b>Success</b>. The <b>Validation </b>sealed class is:</div>
<br />
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;">sealed class Validation<out E, out A> {</span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"> class Failure<out E, out A>internal constructor(val value: E) : Validation<E, A>()</span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"> class Success<out E, out A>internal constructor(val value: A) : Validation<E, A>()</span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: white; color: #222222; font-family: arial; font-size: x-small;"></span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;">}</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
As before, the constructors for <b>Failure</b> and <b>Success </b>are <b>internal </b>and we create instances with the factory functions:</div>
<div>
</div>
<br />
<div style="orphans: 2; text-align: justify; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; widows: 2;">
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val failed: Validation<String, Int> = failure("bug")</span><br />
<span face=""arial" , "helvetica" , sans-serif">val succeeded: Validation<String, Int> = success(25)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(true, failed.isFailure())</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(false, succeeded.isFailure())</span></span></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<b>Validation</b> is a general purpose type for use with error handling:</div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun parseInt(text: String): Validation<String, Int> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> try {</span><br />
<span face=""arial" , "helvetica" , sans-serif"> success(Integer.parseInt(text))</span><br />
<span face=""arial" , "helvetica" , sans-serif"> } catch (ex: NumberFormatException) {</span><br />
<span face=""arial" , "helvetica" , sans-serif"> failure("parseInt: bad number format: $text")</span><br />
<span face=""arial" , "helvetica" , sans-serif"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(success(123), parseInt("123"))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(failure("parseInt: bad number format: ken"), parseInt("ken"))</span></span></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<b style="font-family: Arial, Helvetica, sans-serif;">Pattern matching</b></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
Like in the<span style="font-weight: 400;"> </span><b>Option</b><span style="font-weight: 400;"> </span>class the<span style="font-weight: 400;"> </span><b>Validation</b>, <b>Failure</b> and<span style="font-weight: 400;"> </span><b>Success </b>type names can be used in application code. The type names can be used in user-defined functions. The function<span style="font-weight: 400;"> </span><b>swap </b>supports mapping over both arguments at the same time. Its signature is shown in the following code.</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun <E, A> Validation<E, A>.swap(): Validation<A, E> {</span><br />
<span face=""arial" , "helvetica" , sans-serif"> return when(this) {</span><br />
<span face=""arial" , "helvetica" , sans-serif"> is Failure -> success(this.value)</span><br />
<span face=""arial" , "helvetica" , sans-serif"> is Success -> failure(this.value)</span><br />
<span face=""arial" , "helvetica" , sans-serif"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif">} // swap</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val failed: Validation<String, Int> = failure("bug")</span><br />
<span face=""arial" , "helvetica" , sans-serif">val succeeded: Validation<String, Int> = success(25)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(success("bug"), failed.swap())</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(failure(25), succeeded.swap())</span></span><br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
The function <b>swap</b> flips the Failure/Success values.</div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<span style="font-family: arial;"><b>Some Validation operations</b></span></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
The <b>Validation</b> class includes many of the functions we saw with the<span style="font-weight: 400;"> </span><b>Either </b>class.<span style="font-weight: 400;"> </span><b>Validation </b>class functions include<span style="font-weight: 400;"> </span><b>exists</b>,<span style="font-weight: 400;"> </span><b>fold</b><b style="font-weight: 400;"> </b>and<span style="font-weight: 400;"> </span><b>map</b>. The <b>map </b>function has the signature:</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-family: arial; font-size: x-small;">
fun <B> map(f: (A) -> B): Validation<E, B></span></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
and applies function<span style="font-weight: 400;"> </span><b>f </b>if this is a <b>Success</b>.</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val failed: Validation<String, Int> = failure("bug")</span><br />
<span face=""arial" , "helvetica" , sans-serif">val succeeded: Validation<String, Int> = success(25)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(failure("bug"), failed.map(isEven))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(success(false), succeeded.map(isEven))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(success(true), succeeded.map(isOdd))</span></span><br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="margin: 0px;">
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="font-family: "times new roman";">The </span><b style="font-family: "Times New Roman";">Validation</b><span style="font-family: "times new roman";"> </span><span style="font-family: "times new roman";">type is also an </span><i style="font-family: "Times New Roman";">applicative functor</i><span style="font-family: "times new roman";">. </span>The <b style="font-family: "Times New Roman";">Validation</b><span style="font-family: "times new roman";"> </span>type as an applicative functor includes the extension function <b>ap</b>:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial; font-size: x-small;">fun <E, A, B> Validation<E, A>.ap(se: Semigroup<E>, f: Validation<E, (A) -> B>): Validation<E, B></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
which applies the wrapped function to the receiver <b>Validation</b>. If two or more errors are encountered they are combined using the <i>semigroup </i>instance.</div>
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val failed: Validation<String, Int> = failure("bug")</span><br />
<span face=""arial" , "helvetica" , sans-serif">val succeeded: Validation<String, Int> = success(25)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(failure("bug"), failed.ap(stringSemigroup, success{n: Int -> isEven(n)}))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(success(false), succeeded.ap(stringSemigroup, success{n: Int -> isEven(n)}))</span></span><br />
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div style="color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
When mapping functions over the <b>Validation</b><b> </b>functor with <b>fmap/map </b>we have provided a unary function for the mapping. What do we get if we provide a curried binary function? The answer is we get a unary function wrapped in a <b>Validation</b><b> </b>as shown for the value binding <b>vf</b> and <b>vs</b>.</div>
<div style="color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val failed: Validation<String, Int> = failure("bug")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val err: Validation<String, Int> = failure("error")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val succeeded: Validation<String, Int> = success(25)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val vf: Validation<String, (Int) -> Int> = {m: Int -> {n: Int -> m + n}} dollar failed</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val vs: Validation<String, (Int) -> Int> = {m: Int -> {n: Int -> m + n}} dollar succeeded</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(success(50), succeeded.ap(stringSemigroup, vs))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(failure("errorbug"), err.ap(stringSemigroup, vf))</span></div></div>
<div style="color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
</div>
</div>
<div>
<div style="margin: 0px;">
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
Suppose we need to validate a person's name and age where the values are supplied through two text values. The classes we wish to construct from the text are:</div>
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">data class Name(val name: String)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">data class Age(val age: Int)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">data class Person(val name: Name, val age: Age)</span></span><br />
<span style="font-family: "times new roman";"><br /></span>
<span style="font-family: "times new roman";">A name is valid provided it is non-empty and an age is valid if it is non-negative. The checks are made with the functions <b>makeName </b>and <b>makeAge</b>:</span><br />
<span style="font-family: "times new roman";"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun makeName(name: String): Validation<String, Name> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> if (name == "") failure("Name is empty") else success(Name(name))</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">fun makeAge(age: Int): Validation<String, Age> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> if (age < 0) failure("Age out of range") else success(Age(age))</span></span><br />
<span style="font-family: "times new roman";"><br /></span></div>
</div>
<div>
<div style="margin: 0px;">
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
We are using <b>Validation </b>with the result of these two validation functions. To combine the results we use the applicative f<b>map2 </b>function, a binary version of <b>fmap</b>:</div>
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div style="margin: 0px;"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun makePerson(name: String, age: Int): Validation<String, Person> =</span></div><div style="margin: 0px;"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fmap2(stringSemigroup, makeName(name), makeAge(age)){name: Name -> {age: Age -> Person(name, age)}}</span></div></div>
<div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="font-weight: 400;">
<br /></div>
In the first assert we have an invalid age. In the second assert we have an invalid name and an invalid age. The string semigroup concatenates the two failure messages. The final assertion makes a valid <b>Person </b>instance.<br />
<div style="font-weight: 400;">
<br /></div>
</div>
<div style="margin: 0px;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(failure("Age out of range"), makePerson("Ken", -5))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(failure("Age out of rangeName is empty"), makePerson("", -5))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(success(Person(Name("Ken"), Age(25))), makePerson("Ken", 25))</span></span></div>
<div style="margin: 0px;">
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<div style="margin: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px;">
<div style="margin: 0px;"><div><div style="color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><div style="-webkit-text-stroke-width: 0px;"><div style="margin: 0px;"><span style="font-family: arial;"><b>Case Study</b></span></div></div><div style="font-family: "times new roman";"><div style="margin: 0px;"><div><br /></div><div></div></div></div></div><div style="margin: 0px;"><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-weight: 400;">We repeat here the second case study introduced in the </span><b>Either</b> type blog. In this a user form comprises text fields for the user last name, the first name and the email. The requirements are that the last name is fully capitalized, the first name is capitalized on the initial letter, and that the email be correctly structured. After accepting the three fields, objects for the classes <b style="font-weight: 400;">LastName</b>, <b style="font-weight: 400;">FirstName </b>and <b style="font-weight: 400;">Email </b>are constructed then used to create an instance of the <b style="font-weight: 400;">Person</b> class.</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-family: "Times New Roman";">The standard technique for the construction of objects that need to honor a set of constraints is the </span><i style="font-family: "Times New Roman";">smart constructor idiom</i><span style="font-family: "Times New Roman";">. This is illustrated for the class </span><b style="font-family: "Times New Roman";">LastName</b><span style="font-family: "Times New Roman";">, using <b>Validation</b> </span><span style="font-family: "Times New Roman";">for the error handling. Since it is meaningless </span>to have a <b>Failure</b> with no errors then we use the type Failure<NonEmptyList<Error>, A> where <b>Error </b>is some error type. We start with:</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">typealias Error = String</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">typealias ValidationNelError<A> = ValidationNel<Error, A></span></div></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">Typically, <b>Error </b>would be a sealed data class with sub-types for the various error types. The type name <b>ValidationNel </b>is provided by <b>Dogs </b>and is an alias for Validation<NonEmptyList<E>, A>. The application alias <b>ValidationNelError </b>provides a compact representation for Validation<NonEmptyList<Error>, A>.</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">The class <b>LastName </b>is:</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">data class LastName(val lastName: String) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fun create(lastName: String): ValidationNelError<LastName> {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return if (lastName.length < 2)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> failureNel("Last name too short: $lastName")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> else if (!regex.matches(lastName))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> failureNel("Last name malformed: $lastName")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> else</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> successNel(LastName(lastName))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> private val regex: Regex = Regex("[A-Z][A-Z]*")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // LastName</span></div></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">The same scheme is used for the classes <b>FirstName </b>and <b>Email</b>.</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">Since the <b>Either </b>class is a monad we used the monadic <b>bind</b> to implement the smart constructor for the <b>Person </b>class. However, the <b>Validation </b>class is not a monad and we have no <b>bind</b> function. The issue is that the applicative functor implied by <b>Validation</b> being a monad does not equal the applicative functor defined on <b>Validation</b>.</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">We also know that the monad fails fast and can only identify the first error. Applicatives allow us to compose independent operations and evaluate each one. Even if an intermediate evaluation fails. This allows us to collect error messages instead of returning only the first error that occurred. A classic example where this is useful is the validation of user input. We would like to return a list of all invalid inputs rather than aborting the evaluation after the first error. We see this in the <b>Person</b> class:</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">data class Person(val lastName: LastName, val firstName: FirstName, val email: Email) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fun create(lastName: String, firstName: String, email: String): ValidationNelError<Person> {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val vLastName: ValidationNelError<LastName> = LastName.create(lastName)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val vFirstName: ValidationNelError<FirstName> = FirstName.create(firstName)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val vEmail: ValidationNelError<Email> = Email.create(email)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val ctor: (LastName) -> (FirstName) -> (Email) -> Person = C3(::Person)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return ctor dollar vLastName appliedOver vFirstName appliedOver vEmail</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // Person</span></div></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">and in the following three examples:</div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> success(Person(LastName("BARCLAY"), FirstName("Ken"), Email("me@gmail.com"))),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person.create("BARCLAY", "Ken", "me@gmail.com")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> failure(NonEmptyListF.singleton("First name malformed: kenneth")),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person.create("BARCLAY", "kenneth", "me@gmail.com")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> failure(NonEmptyListF.of("First name malformed: kenneth", "Last name malformed: Barclay")),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person.create("Barclay", "kenneth", "me@gmail.com")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;">Observe how the third example identifies the malformed first name and the malformed last name.</div></div></div></div></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div><div style="color: black; font-family: "times new roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><div style="font-family: "Times New Roman";"><div><br /></div><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;"><br /></span></div></div></div></div></div><div style="color: black; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></div></div></div></div>
</div>
</div>
Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-4506331202699887862022-02-27T08:14:00.005-08:002022-11-04T07:39:05.476-07:00Kotlin: Either type<span style="font-family: arial; font-size: large;"><b>Kotlin: Either type</b></span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;"><i><span style="background-color: white; color: #515151;">Just as its english counterpart describes, Either </span><span style="background-color: white; color: #515151;">can represent one value or another. Scenarios where this might be the return value from a function where you may get the successful result value or you might get an error value.</span></i></span><i> The class is included in the custom library <b>Dogs</b>.</i></div>
<br />
<br />
<br /><div style="text-align: justify;">The <b>Option </b>type allows us to represent failures and exceptions with ordinary values and provide functions that abstract out common patterns of error handling and recovery. The functions <b>bind </b>and <b>ap </b>over the <b>Option </b>type did just this. One issue with the <b>Option </b>type is that it does not report what is wrong in an exceptional case. All we have is <b>None</b>, indicating that there is no value that can be delivered.</div><div style="text-align: justify;"><br /></div><div>
<div style="text-align: justify;">
<span style="background-color: white;"><span style="color: #222222;"><span style="font-family: inherit;"><b>Either </b>is a container type with two type parameters: An </span></span><code style="box-sizing: border-box; color: #222222; font-family: inherit; margin: 0px; padding: 0px;">Either<A, B></code><span style="color: #222222; font-family: inherit;"> instance can contain either an instance of </span><code style="box-sizing: border-box; color: #222222; font-family: inherit; margin: 0px; padding: 0px;">A</code><span style="color: #222222; font-family: inherit;">, or an instance of </span><code style="box-sizing: border-box; color: #222222; font-family: inherit; margin: 0px; padding: 0px;">B (a <i>disjoint type</i>)</code><span style="color: #222222; font-family: inherit;">. </span></span><span style="background-color: white; font-family: inherit;"><span style="color: #222222;"><b>Either </b>has exactly two sub types, <b>Left </b>and <b>Right</b></span><span style="color: #222222;">. If an Either<A, B></span><span style="color: #222222;"> </span><span style="color: #222222;">object contains an instance of <b>A</b></span><span style="color: #222222;">, then the <b>Either </b>is a <b>Left</b></span><span style="color: #222222;">. Otherwise it contains an instance of <b>B</b></span><span style="color: #222222;"><b> </b></span><span style="color: #222222;">and is a <b>Right</b></span><span style="color: #222222;">. The <b>Either </b>sealed class is:</span></span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: inherit;"><span style="color: #222222;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;">sealed class Either<out A, out B> {</span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"> class Left<out A, out B>internal constructor(val value: A) : Either<A, B>()</span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"> class Right<out A, out B>internal constructor(val value: B) : Either<A, B>()</span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: white; color: #222222; font-family: arial; font-size: x-small;"></span></div>
<div style="text-align: justify;">
<span style="color: #222222; font-family: arial; font-size: x-small;">}</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
As before, the constructors for <b>Left </b>and <b>Right</b> are <b>internal </b>and we create instances with the factory functions:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(true, left<String, Int>("ken").isLeft())</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(false, right<String, Int>(25).isLeft())</span></div>
<div>
<br /></div>
<div>
<b>Either </b>is a general purpose type for use whenever you need to deal with a result that can be one of two possible values. Nevertheless, error handling is a popular use case for it, and by convention <b>Left </b>represents the error case and <b>Right </b>the success value:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun parseInt(text: String): Either<String, Int> =</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> try {</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> right(Integer.parseInt(text))</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } catch (ex: NumberFormatException) {</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("parseInt: bad number format: $text")</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(right(123), parseInt("123"))</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(left("parseInt: bad number format: ken"), parseInt("ken"))</span></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<b style="font-family: Arial, Helvetica, sans-serif;">Pattern matching</b></div>
<div>
<br /></div>
<div>
Like the <b>Option</b> class the <b>Either</b>, <b>Left </b>and <b>Right</b> type names can be used in application code. The type names can be used in user-defined functions. The function <b>bimap</b> supports mapping over both arguments at the same time. Its signature is shown in the following code.<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun <A, B, C, D> bimap(either: Either<A, B>, f: (A) -> C, g: (B) -> D): Either<C, D> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> when (either) {</span><br />
<span face=""arial" , "helvetica" , sans-serif"> is Either.Left -> left(f(either.value))</span><br />
<span face=""arial" , "helvetica" , sans-serif"> is Either.Right -> right(g(either.value))</span><br />
<span face=""arial" , "helvetica" , sans-serif"> } // bimap</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">class DomainError(val text: String?) : Exception(text)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val currentDate: Either<Exception, Calendar> = // simple definition</span><br />
<span face=""arial" , "helvetica" , sans-serif"> right(GregorianCalendar(2020, 4, 1))</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val res: Either<Exception, Long> = bimap(</span><span face=""arial" , "helvetica" , sans-serif">currentDate,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> {ex -> DomainError(ex.message)}, </span><br />
<span face=""arial" , "helvetica" , sans-serif"> {date -> date.timeInMillis}</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(right(1588287600000), res)</span></span><br />
<br />
The function <b>f </b>is applied to the wrapped value if it is a <b>Left </b>instance and the function <b>g </b>is applied to the wrapped value if it is a <b>Right </b>instance. The <b>val </b>binding for <b>currentDate </b>wraps a calendar value in a <b>Right</b>. Applying the <b>bimap </b>function to it we make a <b>DomainError </b>if the first parameter is a <b>Left</b>. If the first parameter is a <b>Right </b>we convert the wrapped calendar to its milliseconds.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="font-family: arial;"><b>Some Either operations</b></span></div>
<div>
<br /></div>
<div>
The <b>Either </b>class includes many of the functions we saw with the <b>Option </b>class. <b>Either </b>class functions include <b>exists</b>, <b>fold</b>, <b>getOrElse </b>and <b>map</b>. The <b>fold </b>function has the signature:<br />
<br /><span style="font-family: arial; font-size: x-small;">
fun <C> fold(fa: (A) -> C, fb: (B) -> C): C</span><br />
<br />
and applies function <b>fa </b>if this is a <b>Left</b> or function <b>fb</b> if this is a <b>Right</b>. A consequence is that <b>bimap </b>is a special case of <b>fold </b>as in:<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">class DomainError(val text: String?) : Exception(text)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val currentDate: Either<Exception, Calendar> = // simple definition</span><br />
<span face=""arial" , "helvetica" , sans-serif"> right(GregorianCalendar(2020, 4, 1))</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val res: Either<Exception, Long> = currentDate.fold(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> {ex -> left(DomainError(ex.message))},</span><br />
<span face=""arial" , "helvetica" , sans-serif"> {date -> right(date.timeInMillis)}</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(right(1588287600000), res)</span></span><br />
<br />
The <b>Either </b>type is <i>right-biased</i>, so functions such as <b>map </b>and <b>bind</b> apply only to the <b>Right</b> case. This right-bias makes <b>Either </b>convenient in, for example, a monadic context.<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(left("Ken"), left<String, Int>("Ken").map{n -> 2 * n})</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(right(4), right<String, Int>(2).map{n -> 2 * n})</span></span><br />
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="font-family: arial;"><b>Case Study</b></span></div>
<div>
<br /></div>
<div>
A <b>Project </b>represents some work hosted on a repository service such as GitHub. Each <b>Project </b>records its URL and the list of contributors. Our purpose is to identify those projects with no contributors and in need of support, and at the same time a list of all contributors. Here is how we process our project list:<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">class Project(val url: URL, val contributors: List<String>)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val git: List<Project> = ListF.of(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> Project(URL("http://github.com/project/ai"), ListF.of()),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> Project(URL("http://github.com/project/algol"), ListF.of("EdsgerD", "JohnB", "PeterN", "KenB")),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> Project(URL("http://github.com/project/antlr"), ListF.of("TerranceP")),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> Project(URL("http://github.com/project/data"), ListF.of("KenB", "JohnS")),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> Project(URL("http://github.com/project/ml"), ListF.of()),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> Project(URL("http://github.com/project/system"), ListF.of("BrianK", "DennisR"))</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val checked: List<Either<URL, List<String>>> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> git.map{project -></span><br />
<span face=""arial" , "helvetica" , sans-serif"> if (project.contributors.isEmpty())</span><br />
<span face=""arial" , "helvetica" , sans-serif"> left<URL, List<String>>(project.url)</span><br />
<span face=""arial" , "helvetica" , sans-serif"> else</span><br />
<span face=""arial" , "helvetica" , sans-serif"> right<URL, List<String>>(project.contributors)</span><br />
<span face=""arial" , "helvetica" , sans-serif"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val support: List<Option<URL>> = checked.bind{either -> ListF.singleton(either.fold({ url -> some(url)}, {none()}))}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val supportReq: List<Option<URL>> = support.filter{option: Option<URL> -> (option.isDefined())}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val supportRequired: Option<List<URL>> = supportReq.sequenceOption()</span></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ListF.of(URL("http://github.com/project/ai"), URL("http://github.com/project/ml")),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> supportRequired.getOrElse(ListF.empty())</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val supporters: List<String> = checked.bind{either -> either.fold({ListF.empty<String>()}, {names -> names})}.removeDuplicates()</span></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ListF.of("EdsgerD", "JohnB", "PeterN", "KenB", "TerranceP", "JohnS", "BrianK", "DennisR"),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> supporters</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span></span><br />
<br />
We create in <b>checked </b>a list of <b>Either </b>values, with the <b>Left </b>instances representing unsupported projects and the <b>Right </b>instances containing the contributors. The sequence of <b>val </b>bindings <b>support </b>is a <b>List </b>of <b>Option</b>s wrapping the URL; <b>supportReq </b>is also a <b>List </b>of <b>Option</b>s but without any <b>None </b>instances; <b>supportRequired </b>is a <b>List </b>of URLs wrapped in an <b>Option</b>. The <b>val </b>binding <b>supporters </b>is the <b>List </b>of contributors.</div><div><br /></div><div><br /></div><div><br /></div><div><span style="font-family: arial;"><b>Case Study</b></span></div><div><br /></div><div><span style="font-family: "times new roman";">A user input form comprises text fields for the user last name, the first name and the email. The requirements are that the last name is fully capitalized, the first name is capitalized on the initial letter, and that the email be correctly structured. After accepting the three text fields for the classes, </span><b style="font-family: "times new roman";">LastName</b><span style="font-family: "times new roman";">, </span><b style="font-family: "times new roman";">FirstName </b><span style="font-family: "times new roman";">and </span><b style="font-family: "times new roman";">Email </b><span style="font-family: "times new roman";">are constructed then used to create an instance of the </span><b style="font-family: "times new roman";">Person</b><span style="font-family: "times new roman";"> class.</span></div><div><span style="font-family: times new roman;"><br /></span></div><div><span style="font-family: "Times New Roman";">The standard technique for the construction of objects that need to honor a set of constraints is the </span><i>smart constructor idiom</i><span style="font-family: "Times New Roman";">. This is illustrated for the class </span><b>LastName</b><span style="font-family: "Times New Roman";">, using <b>Either </b></span><span style="font-family: "Times New Roman";">for the error handling. We start with:</span></div><div><br /></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">typealias Error = String</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">data class LastName(val lastName: String) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fun create(lastName: String): Either<Error, LastName> {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return if (lastName.length < 2)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("Last name too short: $lastName")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> else if (!regex.matches(lastName))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("Last name malformed: $lastName")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> else</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> right(LastName(lastName))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> private val regex: Regex = Regex("[A-Z][A-Z]*")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // LastName</span></div><div><span style="font-family: "times new roman";"><br /></span></div><div><span style="font-family: "times new roman";">Typically, </span><b style="font-family: "times new roman";">Error </b><span style="font-family: "times new roman";">would be a sealed class with sub-types for the various error types. Also we might make the constructor for <b>LastName </b>private so that users must use function <b>create</b>.</span></div><div><span style="font-family: "times new roman";"><br /></span></div><div><span style="font-family: "times new roman";">The same scheme is used for the classes </span><b style="font-family: "times new roman";">FirstName </b><span style="font-family: "times new roman";">and </span><b style="font-family: "times new roman";">Email</b><span style="font-family: "times new roman";">.</span></div><div><span style="font-family: "times new roman";"><br /></span></div><div><span style="font-family: "times new roman";">Since the </span><b style="font-family: "times new roman";">Either </b><span style="font-family: "times new roman";">class is a monad we used the monadic </span><b style="font-family: "times new roman";">bind</b><span style="font-family: "times new roman";"> to implement the smart constructor for the </span><b style="font-family: "times new roman";">Person </b><span style="font-family: "times new roman";">class:</span></div><div><span style="font-family: "times new roman";"><br /></span></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">data class Person(val lastName: LastName, val firstName: FirstName, val email: Email) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> companion object {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fun create(lastName: String, firstName: String, email: String): Either<Error, Person> {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val eLastName: Either<Error, LastName> = LastName.create(lastName)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val eFirstName: Either<Error, FirstName> = FirstName.create(firstName)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val eEmail: Either<Error, Email> = Email.create(email)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return eLastName.bind{lastName -></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> eFirstName.bind{firstName -></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> eEmail.bind{email -></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> inject(Person(lastName, firstName, email))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // create</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // Person</span></div></div><div><span style="font-family: times new roman;"><br /></span></div><div><span style="font-family: "times new roman";">We know that the monad fails fast and so can only identify the first error. We see this in the second and third assert:</span></div><div><span style="font-family: "times new roman";"><br /></span></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> right(Person(LastName("BARCLAY"), FirstName("Ken"), Email("me@gmail.com"))),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person.create("BARCLAY", "Ken", "me@gmail.com")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("First name malformed: kenneth"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person.create("BARCLAY", "kenneth", "me@gmail.com")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("Last name malformed: Barclay"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> Person.create("Barclay", "kenneth", "me@gmail.com")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div></div><div><div><br /></div><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div></div><div><span style="color: black;"><br /></span></div></div>
</div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-84456646821087331112020-08-17T07:52:00.000-07:002020-08-17T07:52:19.346-07:00Kotlin: Parser Combinator<p> <b style="font-family: arial, helvetica, sans-serif; font-size: large;">Kotlin: Parser Combinator</b></p><div style="text-align: justify;"><div><i>A parser combinator is a higher-order function that accepts several </i><i>parsers as input and returns a new parser as its output. In this context, a parser is a function </i><i>accepting strings as input and returning some structure as output, typically a parse tree</i><i>. Parser </i><i>combinators enable a recursive descent parsing strategy that facilitates modular piecewise </i><i>construction and testing. This parsing technique is called combinatory parsing.</i></div><div><i><br /></i></div><div><div><i>In a programming language such as Kotlin that has first-class functions, parser combinators can be </i><i>used to combine basic parsers to construct parsers for more complex rules. For example, </i><i>a production rule of a context-free grammar (CFG) may have one or more alternatives and </i><i>each alternative may consist of a sequence of non-terminal(s) and/or terminal(s)</i><i>. If a </i><i>simple parser is available for each of these alternatives, a parser combinator can be </i><i>used to combine each of these parsers, returning a new parser which can recognise any </i><i>or all of the alternatives.</i></div><div><i><br /></i></div><div><i>This blog describes a parser combinator written in Kotlin. The features of Kotlin made it possible to mirror much of the original Haskell code from which it was developed.</i></div></div></div><br /><br /><br /><span style="font-family: arial;"><b>ParsecT</b></span><div><br /></div><div style="text-align: justify;"><b>ParsecT </b>is the main parser and the central data type in this library. The class is parametrized and defined as:</div><div><br /></div><div><span style="font-family: arial; font-size: small;">class ParsecT<TOK, U, A, Z></span></div><div><br /></div><div style="text-align: justify;">where <b>TOK </b>is the type of elements in the input stream (commonly <b>Char</b>), <b>U </b>is the user state, <b>A </b>is the return type, and <b>Z </b>is the value type when an instance is invoked. The class is represented by a single function type property and the member functions deliver a new instance with a suitably modified function property. Hence the class represents a lazy object which only executes when it is finally invoked.</div><div><br /></div><div style="text-align: justify;">The most convenient way to define various parsers is to define a custom type synonym for your parser. The library defines a <b>typealias </b>entitled <b>Parser</b>:</div><div><br /></div><div><span style="font-family: arial; font-size: small;">typealias Parser<A> = ParsecT<Char, Unit, A, Unit></span></div><div><br /></div><div>where the return type <b>A </b>is still a parameter and the input stream is a sequence of <b>Char</b>s.</div><div><br /></div><div>The object declaration:</div><div><br /></div><div><span style="font-family: arial; font-size: small;">object ParsecTF</span></div><div><br /></div><div style="text-align: justify;">includes a set of related functions that either operate on one or more <b>ParsecT </b>parameters or delivers a <b>ParsecT</b> instance.</div><div><br /></div><div><br /></div><div><br /></div><div><span style="font-family: arial;"><b>Object declarations CombinatorF, CharacterF and StringF</b></span></div><div><br /></div><div style="text-align: justify;">The object declaration <b>CombinatorF </b>includes a number of functions used to combine parsers. For example, function <b>many</b> parses none or more occurrences of a given parser. Its signature is:</div><div><br /></div><div><span style="font-family: arial; font-size: small;">fun <TOK, U, A, Z> many(parsec: ParsecT<TOK, U, A, Z>): ParsecT<TOK, U, List<A>, Z></span></div><div><br /></div><div style="text-align: justify;">Note that the return type for the generated parser is a List<A> where the given parser returns the type A.</div><div><br /></div><div style="text-align: justify;">The object declaration <b>CharacterF </b>includes a number of val bindings and function declarations for parsing individual characters. The function declarations in <b>CharacterF </b>are like function <b>oneOf </b>which returns a parser that succeeds if the current input character is in the sequence of character parameters. Its signature is:</div><div><br /></div><div><span style="font-family: arial; font-size: small;">fun oneOf(vararg chars: Char): Parser<Char></span></div><div><br /></div><div style="text-align: justify;">The val bindings are predefined character parsers. For example, the parser <b>colon </b>will recognize a ':' character in the input. The parser <b>dollar </b>will recognize a '$' character in the input. The parser <b>digit </b>will recognize a single decimal digit in the input.</div><div><br /></div><div style="text-align: justify;">The object declaration <b>StringF </b>includes the function <b>parse </b>to execute a parser against some input given as a <b>String</b>. The declaration is:</div><div><br /></div><div><span style="font-family: arial; font-size: small;">fun <A> parse(parsec: Parser<A>, name: String, text: String): Either<ParseError, A></span></div><div><br /></div><div style="text-align: justify;">The <b>parsec </b>parameter is the parser to execute, the <b>text</b> is the input the parser operates on and <b>name </b>is used to describe the source. The <b>name </b>might be the name of the file from which the text is obtained.</div><div><br /></div><div style="text-align: justify;">The return type is either a parse error or the return value from the parser. If the parser fails then the return is a <b>Left</b> instance wrapped around a <b>ParseError</b>. If the parser succeeds then the return is a <b>Right </b>wrapped around the parser return.</div><div><br /></div><div><br /></div><div><br /><span style="font-family: arial;"><b>The Basics</b></span><div><br /><div style="text-align: justify;"><span style="color: #222222;"><span style="background-color: white;">Most of the val bindings in <b>CharacterF </b>are defined with the member function <b>satisfy</b>:</span></span></div><div style="text-align: justify;"><span style="color: #222222;"><span style="background-color: white;"><br /></span></span></div><div style="text-align: justify;"><span style="color: #222222; font-family: arial; font-size: small;"><span style="background-color: white;">fun satisfy(predicate: (Char) -> Boolean): Parser<Char></span></span></div><div style="text-align: justify;"><span style="color: #222222;"><span style="background-color: white;"><br /></span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span color="" style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px; text-align: start;">This looks at the next character from the current input, and if the <b>predicate </b>function </span><span color="" style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px; text-align: start;">returns true for this character, it 'pops' it from the input and returns it. In this way, the current position in the input string is tracked behind the scenes. A sample use of this function is:</span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span color="" style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px; text-align: start;"><br /></span></span></div><div style="text-align: justify;"><span style="background-color: white; text-align: start;"><div style="color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px; text-align: justify;">val pA: Parser<Char> = satisfy{ch: Char -> (ch == 'A')}</div><div style="color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px; text-align: justify;">assertEquals(right('A'), parse(pA, "", "ABC"))</div><div style="color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px; text-align: justify;">assertTrue(parse(pA, "", "BC").isLeft())</div><div style="color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px; text-align: justify;">println(parse(pA, "", "BC"))</div><div style="color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px; text-align: justify;"><br /></div><div style="color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px; text-align: justify;">with the final print producing:</div><div style="color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px; text-align: justify;"><br /></div><div style="text-align: justify;"><span style="letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;">Left(ParseError(sourcePosition=(1, 1), messages=<[SysUnExpect: B]>))</span></span></div><div style="text-align: justify;"><span style="letter-spacing: -0.17px;"><br /></span></div><div style="text-align: justify;"><span style="letter-spacing: -0.17px;">with the error on the first character (of the first line) with the unexpected character 'B'.</span></div></span></div><div style="text-align: justify;"><div><br /></div><div><br /></div><div><br /></div><div><span style="font-family: arial;"><b>CharacterF.character</b></span></div><div><br /></div><div style="text-align: justify;"><span style="background-color: white; text-align: left;"><span style="font-family: inherit;">This function returns a parser that matches the current character in the text that we are parsing to whatever character you provide it. Its signature is:</span></span></div><div><span style="background-color: white; text-align: left;"><span style="font-family: inherit;"><br /></span></span></div><div><span style="background-color: white; text-align: left;"><span style="font-family: arial; font-size: small;">fun character(ch: Char): Parser<Char></span></span></div><div><span style="background-color: white; text-align: left;"><br /></span></div><div><span style="background-color: white; text-align: left;">Sample use of this function is:</span></div><div><span style="background-color: white; text-align: left;"><br /></span></div><div><span style="text-align: left;"><div style="background-color: white;"><span style="font-family: arial; font-size: small;">val pCharacter: Parser<Char> = character('H')</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right('H'), parse(pCharacter, "", "Hello"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertTrue(parse(pCharacter, "", "Goodbye").isLeft())</span></div><div style="background-color: white;"><br /></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;"><span>Here, running character(</span><code style="margin: 0px; padding: 0px;">'H')</code><span> returns a parser that will match the single character 'H'. If we use it in parsing our string, which begins with an H, it is perfectly happy. If we try looking for any letter that isn't 'H', we fail. The result is always of type </span><code style="margin: 0px; padding: 0px;">Either<ParseError, Char></code><span>; we get back a </span><code style="margin: 0px; padding: 0px;">Right result</code><span> if the rule was successful, and </span><code style="margin: 0px; padding: 0px;">Left error</code><span> if the rule fails.</span></span></div><div><span style="background-color: white; font-family: inherit;"><span style="font-size: 14px;"><br /></span></span></div><div><span style="background-color: white; font-family: inherit;"><span style="font-size: 14px;"><br /></span></span></div><div><span style="background-color: white; font-family: inherit;"><span style="font-size: 14px;"><br /></span></span></div><div><span style="background-color: white; font-family: arial;"><b>CharacterF.string</b></span></div><div><span style="background-color: white; font-family: inherit;"><span style="font-size: 14px;"><br /></span></span></div><div><span style="background-color: white;"><span style="font-family: inherit;">This function returns a parser that attempts to match the given string of characters:</span></span></div><div><span style="background-color: white; font-size: 14px;"><span style="font-family: inherit;"><br /></span></span></div><div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">val pString: Parser<String> = string("Hello")</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right("Hello"), parse(pString, "", "Hello world"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertTrue(parse(pString, "", "Help").isLeft())</span></div><div style="background-color: white; font-family: inherit; font-size: 14px;"><br /></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;">The parser will consume characters from the input one by one until all characters match or one of them is not as expected. Since both of the above attempts begin with 'Hel', the error complains about an unexpected 'p'. This consuming of characters will become significant when multiple rules are chained together.</span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div><span style="background-color: white; font-family: arial;"><b>CharacterF.oneOf</b></span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;">Sometimes we want to match a range of characters; that's where CharacterF.oneOf comes in handy. Similar to CharacterF.character, except you provide this function a list of characters you're OK with matching:</span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div><span><div style="background-color: white;"><span style="font-family: arial; font-size: small;">val pVowels: Parser<Char> = oneOf('a', 'e', 'i', 'o', 'u')</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right('o'), parse(pVowels, "", "object"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertTrue(parse(pVowels, "", "function").isLeft())</span></div><div style="background-color: white; font-family: inherit; font-size: 14px;"><br /></div><div><span style="background-color: white; font-family: inherit;">Here, we can see that the parser will <span style="margin: 0px; padding: 0px;">consume</span> any single character that is a vowel.</span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;">Parsec comes with pre-prepared rules which do just that, for example CharacterF.anyChar which will consume one of anything:</span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div><span><div style="background-color: white;"><span style="font-family: arial; font-size: small;">val pSymbols: Parser<Char> = anyCharacter</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right('H'), parse(pSymbols, "", "Hello"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right('+'), parse(pSymbols, "", "+-*/"))</span></div><div style="background-color: white; font-family: inherit; font-size: 14px;"><br /></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;">The rule CharacterF.letter will happily consume any lower or uppercase letter, CharacterF.lower will consume any lowercase letter, CharacterF.digit will consume any single decimal digit, and CharacterF.alphaNum any letter or digit.</span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div><span style="background-color: white; font-family: arial;"><b>CombinatorF.many</b></span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;">There are times when you want to parse more than just one letter. CombinatorF.many tries to run whatever rule it is given as an argument repeatedly</span><span style="background-color: white; font-family: inherit;"> until it fails. Even if the rule matches no times, <b>many </b>will return without error, but just give back an empty result. Let's see how it's used:</span></div><div style="font-size: 14px;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right(ListF.of('h', 'h', 'h')), parse(many(character('h')), "", "hhheee"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right(ListF.of()), parse(many(character('e')), "", "hhheee"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right(ListF.of('h', 'h', 'h', 'e', 'e', 'e')), parse(many(letter), "", "hhheee"))</span></div><div style="background-color: white; font-family: inherit; font-size: 14px;"><br /></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;">As we see,CombinatorF.many can't fail, it will match the rule it's given zero times and just return nothing. It'll go as far as it can and give you back everything that matched. CombinatorF.many1 is similar except that the rule provided must match at least once for it to return successfully.</span></div></div><div style="font-size: 14px; text-align: justify;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="font-size: 14px; text-align: justify;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="font-size: 14px; text-align: justify;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: white; font-family: arial;"><b>ParsecT.fmap</b></span></div><div style="font-size: 14px; text-align: justify;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="background-color: white; font-family: inherit;">The <b>ParsecT </b>data type is a <i>functor </i>by supporting the member function <b>fmap </b>which, given any types A and B lets you apply the function (A) -> B to a ParsecT<TOK, U, A, Z> delivering a ParsecT<TOK, U, B, Z>. Thus we can use <b>fmap</b> to transform the return value of a parser:</span></div><div style="font-size: 14px; text-align: justify;"><span style="background-color: white; font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span><div style="background-color: white;"><span style="font-family: arial; font-size: small;">val pTab: Parser<Char> = tab</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">val pSpaces: Parser<String> = pTab.fmap{ch: Char -> " "}</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right(" "), parse(pSpaces, "", "\t"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertTrue(parse(pSpaces, "", "A").isLeft())</span></div><div style="background-color: white; font-family: inherit; font-size: 14px;"><br /></div><div style="background-color: white; font-family: inherit;">Combining <b>fmap</b>, <b>many1</b> and the single character parser <b>digit </b>we can parse a series of decimal digits into an integer:</div><div style="background-color: white; font-family: inherit; font-size: 14px;"><br /></div><div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">val pInteger: Parser<Int> = many1(digit).fmap{digs: List<Char> -></span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;"> digs.foldLeft(0){acc: Int -> {ch: Char -> 10 * acc + (ch.toInt() - '0'.toInt())}}</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">}</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertEquals(right(123), parse(pInteger, "", "123"))</span></div><div style="background-color: white;"><span style="font-family: arial; font-size: small;">assertTrue(parse(pInteger, "", "ABC").isLeft())</span></div><div style="background-color: white;"><span style="font-family: inherit;"><br /></span></div><div style="background-color: white;"><span style="font-family: inherit;"><br /></span></div><div style="background-color: white;"><span style="font-family: inherit;"><br /></span></div><div style="background-color: white;"><span style="font-family: arial;"><b>Combining rules</b></span></div><div style="background-color: white;"><span style="font-family: inherit;"><br /></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span style="background-color: white; color: #212529; text-align: left;">The simplest way to combine parsers is to execute them in succession. <b>ParsecT </b></span><span style="background-color: white; color: #212529; text-align: left;">is a</span><span style="background-color: white; color: #212529; text-align: left;"> <i>monad</i>, and monadic <b>bind </b>is exactly what we use for sequencing our parsers. In the following example we sequence three character parsers to recognize ABC:</span></span></div><div><span style="font-family: inherit;"><span style="background-color: white; color: #212529; text-align: left;"><br /></span></span></div><div><span style="background-color: white; text-align: left;"><span style="color: #212529;"><div><span style="font-family: arial; font-size: small;">val pA: Parser<Char> = character('A')</span></div><div><span style="font-family: arial; font-size: small;">val pB: Parser<Char> = character('B')</span></div><div><span style="font-family: arial; font-size: small;">val pC: Parser<Char> = character('C')</span></div><div><span style="font-family: arial; font-size: small;">val pSequence: Parser<Triple<Char, Char, Char>> =</span></div><div><span style="font-family: arial; font-size: small;"> pA.bind{chA: Char -></span></div><div><span style="font-family: arial; font-size: small;"> pB.bind{chB: Char -></span></div><div><span style="font-family: arial; font-size: small;"> pC.bind{chC: Char -></span></div><div><span style="font-family: arial; font-size: small;"> inj(Triple(chA, chB, chC))</span></div><div><span style="font-family: arial; font-size: small;"> }</span></div><div><span style="font-family: arial; font-size: small;"> }</span></div><div><span style="font-family: arial; font-size: small;"> }</span></div><div><span style="font-family: arial; font-size: small;"><br /></span></div><div><span style="font-family: arial; font-size: small;">assertEquals(right(Triple('A', 'B', 'C')), parse(pSequence, "", "ABC"))</span></div><div><br /></div><div style="text-align: justify;">The object declaration <b>ParsecTF </b>includes the function <b>mapM3 </b>which supports an alternative syntax for sequential execution of monadic parsers:</div><div><br /></div><div><div><span style="font-family: arial; font-size: small;">val pA: Parser<Char> = character('A')</span></div><div><span style="font-family: arial; font-size: small;">val pB: Parser<Char> = character('B')</span></div><div><span style="font-family: arial; font-size: small;">val pC: Parser<Char> = character('C')</span></div><div><span style="font-family: arial; font-size: small;">val pSequence: Parser<Triple<Char, Char, Char>> =</span></div><div><span style="font-family: arial; font-size: small;"> mapM3(pA, pB, pC){chA: Char -> {chB: Char -> {chC: Char -> Triple(chA, chB, chC)}}}</span></div><div><span style="font-family: arial; font-size: small;"><br /></span></div><div><span style="font-family: arial; font-size: small;">assertEquals(right(Triple('A', 'B', 'C')), parse(pSequence, "", "ABC"))</span></div><div><br /></div></div></span></span></div></div></span></div></span></div></span></div></div></span></div><div><span face="" style="background-color: #eeeeee; font-family: inherit; text-align: left;"><br /></span></div><div><span face="" style="background-color: white; font-family: inherit; text-align: left;"><br /></span></div><div><span face="" style="background-color: white; font-family: arial; text-align: left;"><b>Kotlin package declaration parsing</b></span></div><div><span face="" style="background-color: white; font-family: inherit; text-align: left;"><br /></span></div><div style="text-align: justify;"><span face="" style="background-color: white; font-family: inherit; text-align: left;">In this section we develop a simple parser for a Kotlin package declaration. A typical package declaration is:</span></div><div><span face="" style="background-color: white; font-family: inherit; text-align: left;"><br /></span></div><div><span face="" style="background-color: white; font-family: arial; font-size: small; text-align: left;">package com.adt.kotlin.parsec</span></div><div><span face="" style="background-color: white; text-align: left;"><br /></span></div><div style="text-align: justify;"><span style="background-color: white;">comprising the <b>package </b>keyword, one or more spaces and a qualified name. First we define the parsers for the keyword and the dot separator:</span></div><div style="text-align: left;"><span style="background-color: white;"><br /></span></div><div style="text-align: left;"><span style="background-color: white;"><div><span style="font-family: arial; font-size: small;">val pPackageKeyword: Parser<String> = StringF.lexeme(string("package"))</span></div><div><span style="font-family: arial; font-size: small;">val pDot: Parser<Char> = character('.')</span></div><div><br /></div><div style="text-align: justify;"><span style="font-family: inherit;"><span style="color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;">In the original parsec documentation, one of the concepts mentioned is the idea of 'lexeme' parsing. This is a style in which every token parser should also consume and ignore any trailing whitespace. </span><span style="color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;">This is a simple convention which with a bit of care allows skipping whitespace exactly once wherever it needs to be skipped. The function <b>lexeme </b>performs this task, skipping any whitespace following the package keyword.</span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span style="color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><br /></span></span></div><div style="text-align: justify;"><span style="font-family: inherit;"><span style="color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;">An identifier </span><span style="color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px; text-align: left;">must start with a letter or underscore, and then followed by zero or more letters, underscores or digits in any combination:</span></span></div></span><div style="background-color: white; text-align: justify;"><span style="font-family: inherit;"><span style="color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><br /></span></span></div><div style="text-align: justify;"><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;">val leading: Parser<Char> = satisfy{ch: Char -> Character.isJavaIdentifierStart(ch)}</span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;">val trailing: Parser<Char> = satisfy{ch: Char -> Character.isJavaIdentifierPart(ch)}</span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;">val pIdentifier: Parser<String> =</span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;"> leading.bind{leadingChar: Char -></span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;"> many(trailing).bind{trailingChars: List<Char> -></span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;"> inj(ListF.cons(leadingChar, trailingChars).charsToString())</span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;"> }</span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;"> } // pIdentifier</span></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px;"><br /></div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px;">A qualified identifier comprises one or more identifiers separated by a dot.</div><div style="background-color: white; color: rgba(0, 0, 0, 0.8); font-family: inherit; letter-spacing: -0.17px;"><br /></div><div style="background-color: white;"><span style="letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;">val pQualifiedName: Parser<QualifiedName> =</span></span></div><div style="background-color: white;"><span style="letter-spacing: -0.17px;"><span style="font-family: arial; font-size: small;"> CombinatorF.sepBy1(pIdentifier, pDot).fmap{names: List<String> -> QualifiedName(names)}</span></span></div><div style="background-color: white;"><span style="letter-spacing: -0.17px;"><br /></span></div><div><span style="background-color: white; text-align: left;"><span style="font-family: inherit;">Function <b>sepBy1 </b>takes two arguments, a rule to parse items, and a rule to parse separators and returns a list of whatever the rule returns. Using <b>fmap </b>we convert this into a <b>QualifiedName</b>:</span></span></div><div><span style="background-color: white; text-align: left;"><span style="font-family: inherit;"><br /></span></span></div><div><span style="background-color: white; text-align: left;"><span style="font-family: arial; font-size: small;">data class QualifiedName(val names: List<String>)</span></span></div><div><span style="background-color: white; text-align: left;"><br /></span></div><div><span style="background-color: white; text-align: left;">The parser for a package declaration is then:</span></div><div><span style="background-color: white; text-align: left;"><br /></span></div><div><span style="background-color: white; text-align: left;"><div><span style="font-family: arial; font-size: small;">val pPackageDeclaration: Parser<PackageDeclaration> =</span></div><div><span style="font-family: arial; font-size: small;"> pPackageKeyword.bind{_: String -></span></div><div><span style="font-family: arial; font-size: small;"> pQualifiedName.bind{qualifiedName: QualifiedName -></span></div><div><span style="font-family: arial; font-size: small;"> inj(PackageDeclaration(qualifiedName))</span></div><div><span style="font-family: arial; font-size: small;"> }</span></div><div><span style="font-family: arial; font-size: small;"> } // pPackageDeclaration</span></div><div><br /></div><div>where:</div><div><br /></div><div><span style="font-family: arial; font-size: small;">data class PackageDeclaration(val qualifiedName: QualifiedName)</span></div><div><br /></div><div>We demonstrate it with:</div><div><br /></div><div><div><span style="font-family: arial; font-size: small;">assertEquals(right(PackageDeclaration(QualifiedName(ListF.of("test", "kotlin")))),</span></div><div><span style="font-family: arial; font-size: small;"> parse(pPackageDeclaration, "", "package test.kotlin"))</span></div><div><span style="font-family: arial; font-size: small;">assertTrue(parse(pPackageDeclaration, "", "package test.*").isLeft())</span></div><div><span style="font-family: arial; font-size: small;">assertTrue(parse(pPackageDeclaration, "", "package").isLeft())</span></div><div><span style="font-family: arial; font-size: small;">assertTrue(parse(pPackageDeclaration, "", "import test.kotlin").isLeft())</span></div></div><div><br /></div></span></div></div></div><div><br /></div><div><br />The code for Parsec can be found at:<br /><br />https://github.com/KenBarclay/Parsec<br /><br style="text-align: start;" /></div></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-74105358694519146282020-06-12T06:29:00.006-07:002022-11-15T07:34:17.277-08:00Kotlin: Non Empty List type<span style="font-family: arial; font-size: large;"><b>Kotlin: Non Empty List type</b></span><br />
<br />
<div style="text-align: justify;">
<div class="MsoBodyText">
<i>A non empty list is one with at least one element, but is otherwise identical to the traditional immutable list in complexity and API. Sometimes you have a function that expects a list with at least one element in the function call. We cannot enforce the user to provide a non empty list using either the Kotlin List interface or the List class from the custom <b>Dogs </b>library. Here we present the <b>NonEmptyList </b>class that guarantees to have one or more elements.</i></div>
</div>
<br />
<br />
<br />
<span style="font-family: arial;"><b>Motivation</b></span><br />
<br />
<div style="text-align: justify;">
Consider an order-taking workflow for a manufacturing company. An order might include the customer name, the billing and shipping addresses and a number of order lines. We might consider a <b>List </b>to represent the order lines but a <b>List </b>may be empty and the integrity of a business rule may be violated if we permit an order with zero order lines.</div>
<br />
<div style="text-align: justify;">
Equally, suppose we have some function that operates on a series of one or more values given as a parameter. An obvious choice would be use a <b>List</b> for the parameter type and make a check within the function body that the list length exceeds zero.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
We can use the Kotlin type system to represent what is valid or invalid so that the compiler can check it for us, instead of relying on runtime checks or code comments to ensure the rules are maintained. For this function a more appropriate parameter type would be <b>NonEmptyList </b>which, as its name suggests, contains one or more elements.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
When validating user input we might consider using the <b>Validation </b>class from the custom library (see later). The <b>Validation </b>class has two concrete sub-classes <b>Failure</b> and <b>Success</b>. The <b>Failure</b> class carries a number of error types. Since it is meaningless to have a <b>Failure</b> with no errors then we use the type Failure<NonEmptyList<Error>> where <b>Error </b>is some error type. We discussed this in the Validation type blog.</div>
<br />
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: arial;"><b>Immutable NonEmptyList</b></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<br /></div>
<div class="MsoBodyText">
<span style="font-family: inherit;">The immutable <b>NonEmptyList </b>type is defined as:<o:p></o:p></span></div>
<div class="MsoBodyText">
<br />
<span style="font-family: arial; font-size: x-small;">class NonEmptyList<out A> internal constructor(val hd: A, val tl: List<A>)</span><br />
<br />
Again, since the constructor is tagged internal, a series of factory constructor functions are provided:<br />
<br /><div class="MsoBodyText"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(4, cons(1, cons(2, cons(3, singleton(4)))).size())</span></div><div class="MsoBodyText"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(1, cons(1, cons(2, cons(3, singleton(4)))).head())</span></div><div class="MsoBodyText"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(4, cons(1, cons(2, cons(3, singleton(4)))).last())</span></div><div class="MsoBodyText"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(9, of(1, 2, 3, 4, 5, 6, 7, 8, 9).size())</span></div><div class="MsoBodyText"><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(10, closedRange(1, 10).size())</span></div>
<br />
<div style="text-align: justify;">
Unlike the <b>List</b> class, the member function <b>head</b> of class <b>NonEmptyList</b> is a safe operation that guarantees not to throw an exception. Further, some member functions of <b>NonEmptyList </b>such as <b>map </b>deliver a <b>NonEmptyList </b>result, while others, such as <b>filter</b>, deliver a <b>List </b>result. This is necessary since the predicate to the <b>filter </b>function may not match any element of the <b>NonEmptyList</b>. Here are some examples that deliver <b>List</b>s:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(3, 4, 5), NonEmptyListF.of(1, 2, 3, 4, 5).drop(2))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(), NonEmptyListF.of(1, 2, 3, 4, 5).drop(6))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(2, 4), NonEmptyListF.of(1, 2, 3, 4, 5).filter(isEven))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(), NonEmptyListF.of(1, 2, 3, 4, 5).filter{n -> (n > 10)})</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here are some of the many functions over <b>NonEmptyList</b>s:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(3, NonEmptyListF.of(1, 2, 3, 4, 5)[2])</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(true, NonEmptyListF.of(1, 2, 3, 4, 5).contains(4))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(15, NonEmptyListF.of(1, 2, 3, 4, 5).foldLeft(0){acc -> {el -> acc + el}})</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> NonEmptyListF.of(false, true, false, true, false),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> NonEmptyListF.of(1, 2, 3, 4, 5).map(isEven)</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> NonEmptyListF.of(Pair(1, 'a'), Pair(2, 'b'), Pair(3, 'c')),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> NonEmptyListF.of(1, 2, 3, 4, 5).zip(NonEmptyListF.of('a', 'b', 'c'))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div>
<br /></div>
<div style="text-align: justify;">
<br />
<span style="font-family: arial;"><b>Case Study</b></span><br />
<br />
An important attribute of applicatives is that they compose. Since the <b>NonEmptyList </b>class is an applicative then it supports the <b>fmap3 </b>function which maps a function of three parameters across the elements of three <b>NonEmptyList</b>s. Suppose we have the function <b>volume </b>which computes the volume of a cuboid:<br />
<br />
<span style="font-family: arial; font-size: x-small;">fun volume(length: Int, width: Int, height: Int): Int = length * width * height</span><br />
<br />
Consider that we wish apply this function but each of the dimensions are in <b>NonEmptyList</b>s:<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val lengths: NonEmptyList<Int> = of(2, 3, 4, 5)</span><br />
<span face=""arial" , "helvetica" , sans-serif">val widths: NonEmptyList<Int> = of(6, 7)</span><br />
<span face=""arial" , "helvetica" , sans-serif">val heights: NonEmptyList<Int> = of(7, 8, 9)</span></span><br />
<br />
The <b>fmap3</b> function has the signature:<br />
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">fun <A, B, C, D> fmap3(la: NonEmptyList<A>, lb: NonEmptyList<B>, </span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> lc: NonEmptyList<C>, f: (A) -> (B) -> (C) -> D): NonEmptyList<D></span></span><br />
<br />
and use it with:<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span>val volumes: NonEmptyList<Int> = NonEmptyListF.fmap3(lengths, widths, heights, ::volume)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span><span face=""arial" , "helvetica" , sans-serif">assertEquals(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> NonEmptyListF.of(84, 96, 108, 98, 112, 126, 126, 144, 162, 147, 168, 189, 168, 192, 216, 196, 224, 252, 210, 240, 270, 245, 280, 315),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> volumes</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span></span></span><br />
<br />
where the values 84, 96, 108, 98, ... are produced from 2 * 6 * 7, 2 * 6 * 8, 2 * 6 * 9, 2 * 7 * 7, ...<br /></div><div style="text-align: justify;"><div style="text-align: left;"><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The code for the Dogs library can be found at:</div><div style="text-align: justify;"><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;"><br /></span></div></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-20325242837196048572020-06-02T07:46:00.014-07:002022-11-07T07:16:46.594-08:00Kotlin: List type<span style="font-family: arial; font-size: large;"><b>Kotlin: List type</b></span><br />
<br />
<div style="text-align: justify;">
<div class="MsoBodyText">
<span style="font-family: inherit;"><i>Ordinary data
structures are ephemeral in the sense that making a change to the
structure destroys the old version, leaving only the new one. This is the case
for the <b>List</b> and <b>Map</b> types in the Kotlin standard
library. These <span style="background: white; color: #222222;">imperative data structures</span><span style="background: white; color: #222222;"> operate through in-place mutation of data ─ the data
structure is mutable. In our everyday usage of Kotlin data structures we
mutate lists, arrays and any other type to realise the algorithm that we
implement.</span><o:p></o:p></i></span></div>
<div class="MsoBodyText">
<br /></div>
<br />
<div class="MsoBodyText">
<span style="font-family: inherit;"><i>An important property of functional
data structures is that they always persist ─ updating a functional
data structure does not destroy the existing version, but rather creates a new
version that coexists with the old version. Persistence is achieved by copying
the affected nodes of a data structure and making all changes in the copy
rather than in the original. Because they are never modified directly, all
nodes that are unaffected by an update can be shared between the old and new
versions of the structure without worrying that a change in one version will
inadvertently be visible to the other. Functional data structures are immutable
and persistent.</i></span><span style="font-family: "comic sans ms";"><o:p></o:p></span></div>
</div>
<br />
<br />
<br />
<span style="font-family: arial;"><b>Motivation</b></span><br />
<br />
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Functional
languages exploit persistent data structures, many of them based on the seminal
book by <a href="http://www.cambridge.org/catalogue/catalogue.asp?isbn=0521663504" target="_blank">Chris Okasaki</a>.
Persistent data structures are being embraced by imperative programming languages.
Persistent data structures should be part of every Kotlin programmer’s toolset,
especially one interested in concurrency and parallelism.<o:p></o:p></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText">
<span style="font-family: inherit;">Immutability is important for a
number of reasons:<o:p></o:p></span></div>
<ul>
<li>immutable data makes the code more predictable</li>
<li>immutable data is easier to work with</li>
<li>immutable data encourages a transformational approach</li>
</ul>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">With immutability there can be no
side effects. If there are no side effects it is much easier to reason about
the correctness of the code. The code is then more predictable than its wholly imperative equivalent.<o:p></o:p></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">If data is immutable many common
tasks become much easier: the code is easier to write and to maintain. Fewer
unit tests are required and you only have to check that the function works in
isolation. Concurrency is simpler too since you are not worrying about update
conflicts.<o:p></o:p></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Immutable data promotes a different
programming approach. More emphasis is given to transforming the data instead
of in-place mutation of the data. A greater emphasis on transformation can lead
to more elegant, more modular and more scalable solutions.<o:p></o:p></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Every data structure has its own
unique performance characteristics. A naïve implementation of a persistent data
structure would deliver a very poor performance. </span><span style="font-family: inherit;">Major studies have been done
designing efficient persistent data structures. In many cases they closely
match the performance of their mutable cousins.</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: arial;"><b>Immutable Lists</b></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal" style="line-height: normal; margin-bottom: 0cm; text-align: justify;">
<span style="font-family: inherit;">The
simple list is ubiquitous throughout programming and is probably the most-used
data structure. The list is a collection of references to other objects. The
list can grow dynamically. The list is defined generically so that it can
handle values identically without depending on their type. Since the type of
objects maintained by this collection is arbitrary, the elements of a list can
be another list or map or etc. This way we can create useful data structures of
arbitrary complexity.<o:p></o:p></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText">
<span style="font-family: inherit;">The immutable <b>List </b>type is defined recursively in <b>Dogs </b>as an <i>algebraic data type</i>:<o:p></o:p></span></div>
<div class="MsoBodyText">
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">sealed class List<out A> {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> object Nil : List<Nothing>()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> class Cons<A>(val hd: A, val tl : List<A>) : List<A>()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<br /></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Every list is
constructed with just the two <i>value constructors</i> <b>Nil</b> and <b>Cons</b>. <b>Nil</b> is a
synonym for the empty list while <b>Cons</b>
makes a list by putting an element in front of an existing list. Every list is
either Nil, if empty, or has the form Cons(x, xs), where x is the <i>head</i>
of the list and xs is the <i>tail</i> of the list. The tail is another list.<o:p></o:p></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">The following figure is a sample list using
an empty list (represented by the circle) and <b>Cons</b> cells (represented by the sub-divided rectangles). Each <b>Cons</b> cell stores a single value for its
head and a reference to the remainder for its tail.<o:p></o:p></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoBodyText">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-00RKox80N-uNsLsm-0Ll5D9U4ACDJWHhJerGoPn-YLizqnZBcxvQROCaXjkudZOjTlD5SfN53OV-lY2fZcctF3iSJbvRkMHme5PTx4MobxcQptkNNt1nhvk7NwKE70D3QdR3eU5ZNsQ/s1600/fig10.1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="449" data-original-width="1488" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-00RKox80N-uNsLsm-0Ll5D9U4ACDJWHhJerGoPn-YLizqnZBcxvQROCaXjkudZOjTlD5SfN53OV-lY2fZcctF3iSJbvRkMHme5PTx4MobxcQptkNNt1nhvk7NwKE70D3QdR3eU5ZNsQ/s640/fig10.1.png" width="640" /></a></div>
<div style="text-align: justify;">
<span style="font-family: inherit;">This sample list
would be constructed by creating an empty list with nil() then cons-ing new
elements on to the head with cons(2, nil()). The completed list is assembled
with:</span></div>
</div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText" style="margin-left: 14.2pt;">
<span><span style="font-family: arial; font-size: x-small;">cons(1, cons(2, cons(3, cons(4, nil()))))</span><span style="font-family: inherit;"><o:p></o:p></span></span></div>
<div class="MsoBodyText">
<br />
<div style="text-align: justify;">
The type names <b>Nil </b>and <b>Cons</b> are accessible to application code but the constructors are tagged as <b>internal</b>. Hence we use the factory constructor functions <b>nil </b>and <b>cons</b>. Here are some examples of assembled lists:</div>
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(4, cons(1, cons(2, cons(3, cons(4, nil())))).size())</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(1, cons(1, cons(2, cons(3, cons(4, nil())))).head())</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(false, cons(1, cons(2, cons(3, cons(4, nil())))).isEmpty())</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(4, ListF.of(1, 2, 3, 4).size())</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(10, ListF.closedRange(1, 10).size())</span></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">We can grow a <b>List </b>with the <b>append </b>function:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(5, ListF.of(1, 2, 3, 4).append(5).last())</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(7, ListF.of(1, 2, 3, 4).append(ListF.of(5, 6, 7)).last())</span></span><br />
<br />
<div style="text-align: justify;">
Prepending an element on to the front of a Kotlin <b>ImmutableList </b>with list.add(0, element) is more expensive than adding to the end with list.add(element). By the same argument, adding to the end of the custom immutable <b>List </b>with <b>append </b>is more expensive than prepending with <b>cons</b>. The function <b>append </b>is best avoided when working with large lists.</div>
<div style="text-align: justify;">
<br /></div>
<br />
<br />
<span style="font-family: arial;"><b>Processing immutable lists</b></span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">The custom immutable </span><b style="font-family: inherit;">List</b><span style="font-family: inherit;"> class has the same functionality as that provided by the
Kotlin extension functions on the Java </span><b style="font-family: inherit;">List</b><span style="font-family: inherit;">.
Many are named the same. For example the custom immutable </span><b style="font-family: inherit;">List</b><span style="font-family: inherit;"> class includes the member functions </span><b style="font-family: inherit;">contains</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">count</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">drop</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">dropWhile</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">filter</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">get</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">indexOf</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">isEmpty</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">last</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">map</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">take</b><span style="font-family: inherit;">, </span><b style="font-family: inherit;">takeWhile</b><span style="font-family: inherit;"> and </span><b style="font-family: inherit;">zip</b><span style="font-family: inherit;"> among others. Most bear the same signature as their Kotlin
counterparts.</span></div>
<div style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: inherit;">The following example demonstrates how easy it is to define one function in terms of those provided. Given two indices <b>from </b>and <b>to</b>, the <b>segment</b> is the list containing the elements between <b>from </b>and <b>to </b>inclusive:</span></div>
<div style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun <A> segment(from: Int, to: Int, ls: List<A>): List<A> =</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ls.drop(from).take(to - from + 1)</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.empty(), segment(3, 5, ListF.empty<Int>()))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.empty(), segment(3, 5, ListF.of(1, 2, 3)))</span></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(1, 2, 3), segment(3, 5, ListF.of(1, 1, 1, 1, 2, 3, 3, 1, 1, 4, 5, 5, 5, 5)))</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-size: 11pt; line-height: 115%;"><span style="font-family: inherit;">Every
list is either empty represented by Nil, or is non-empty represented by Cons(
... ). In fact, every list is constructed by repeatedly applying <b>Cons</b> on to an empty list <b>Nil</b>. If we want to define a function
over a list we distinguish between empty and non-empty cases. This leads to a <i>constructor pattern</i> over lists which
will pattern match against either <b>Nil</b>
or <b>Cons</b>.</span></span></div>
<div style="text-align: justify;">
<span style="font-size: 11pt; line-height: 115%;"><span style="font-family: inherit;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="font-family: inherit;">Function
<b>headOption</b> delivers the first
element in the list. If the list is empty the function returns <b>None</b> otherwise it returns the head of
the list wrapped in a <b>Some</b>. The
implementation exploits the pattern matching of sealed classes.</span></span></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="font-family: inherit;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="line-height: 115%;"><span style="font-family: inherit;">The
extension function <b>reverseMap</b> builds
a new list by applying the function to all elements of the receiver, collecting
the result in reverse order. The local function <b>recReverseMap</b> pattern matches against the empty and non-empty list.
As the elements are transformed by the function <b>f</b> they are prepended on to the accumulating parameter <b>acc</b>.</span></span></span></div>
<div style="text-align: justify;">
<span style="font-size: 11pt; line-height: 115%;"><span style="font-family: inherit;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun <A> headOption(ls: List<A>): Option<A> =</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> when (ls) {</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Nil -> none()</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Cons -> some(ls.head())</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun <A, B> List<A>.reverseMap(f: (A) -> B): List<B> {</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> tailrec</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fun recReverseMap(f: (A) -> B, xs: List<A>, acc: List<B>): List<B> {</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return when(xs) {</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Nil -> acc</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Cons -> recReverseMap(f, xs.tail(), cons(f(xs.head()), acc))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // recReverseMap</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return recReverseMap(f, this, ListF.empty())</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // reverseMap</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(none(), headOption(ListF.empty<Int>()))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some("Ken"), headOption(ListF.of("Ken", "John", "Jessie", "Irene")))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(16, 9, 4, 1), ListF.of(1, 2, 3, 4).reverseMap{n -> n * n})</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-size: x-small;"><span style="font-family: arial; line-height: 115%;"></span></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of("JESSIE", "JOHN", "KEN"),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of("Ken", "John", "Jessie").reverseMap{str -> str.toUpperCase()})</span></div>
<div style="text-align: justify;">
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;"><i>Zipping </i>is the process of combining two lists into one list by merging corresponding elements into pairs. The resulting list has the same length as the shorter of the two. Here are some examples:</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.of(Pair(1, 4), Pair(2, 5), Pair(3, 6)), ListF.of(1, 2, 3).zip(ListF.of(4, 5, 6)))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.of(Pair(1, 4), Pair(2, 5)), ListF.of(1, 2).zip(ListF.of(4, 5, 6)))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.of(Pair(1, 4), Pair(2, 5)), ListF.of(1, 2, 3).zip(ListF.of(4, 5)))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.empty(), ListF.of(1, 2, 3).zip(ListF.empty<Int>()))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.empty(), ListF.empty<Int>().zip(ListF.of(4, 5, 6)))</span></span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">In the next illustration the <b>zip </b>function is used to define <b>isOrdered </b>which determines if a <b>List </b>of <b>Int</b>s is in ascending order. Zipping a list with its tail produces pairs of adjacent elements. Function <b>forAll </b>returns true if all the elements match the predicate.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun isOrdered(list: List<Int>): Boolean =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> list.zip(list.tail()).forAll{pair -> (pair.first <= pair.second)}</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(true, isOrdered(ListF.of(1, 2, 3, 4, 5)))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(true, isOrdered(ListF.of(1, 2, 2, 3, 4)))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(false, isOrdered(ListF.of(1, 2, 5, 4, 3)))</span></span><br />
<br /></div>
<div style="text-align: justify;">
<span style="font-size: 14.6667px;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-size: 14.6667px;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-size: 14.6667px;"><span style="font-family: arial;"><b>Immutable Lists and persistence</b></span></span></div>
<div style="text-align: justify;">
<span style="font-size: 14.6667px;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Our list data
structures are immutable. Member functions of the custom class <b>List</b> and the functions defined in <b>ListF</b> working with our list data structure do not modify the state
of the structure. They can only return a new structure if they represent some
change operation. In this setting the lists we create are immutable. A further
consequence of this approach is that the structures are <i>shared</i>.</span><span style="font-family: "comic sans ms";"><o:p></o:p></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">In the following figure presents three lists named <b>xs</b>, <b>ys</b> and <b>zs</b>. The list <b>ys</b> is
obtained by dropping the first three elements from the <b>xs</b> list sharing its final element. The figure also shows
how the list <b>zs</b> also shares part of
the original list <b>xs</b>. </span><span style="font-family: "comic sans ms";"><o:p></o:p></span>By comparison, the <b>drop</b> function from the Kotlin standard library implements this by making a copy of the sub-list.</div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinNFXhlcIE9uB3U_8G9Nwy6F2rpkp6WUrSzRSUI4RvAISz0tcPy_RA6A3r9_Ufv15xp6Zv2E3wTivD3QS3XhVwphY9u2N2OJj5kWAtZVAzhOjhOUu3filM1WiG23oR727ithUcX19W55M/s1600/fig10.2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="449" data-original-width="1488" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinNFXhlcIE9uB3U_8G9Nwy6F2rpkp6WUrSzRSUI4RvAISz0tcPy_RA6A3r9_Ufv15xp6Zv2E3wTivD3QS3XhVwphY9u2N2OJj5kWAtZVAzhOjhOUu3filM1WiG23oR727ithUcX19W55M/s640/fig10.2.png" width="640" /></a></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Here is how the member function <b>drop</b> is implemented:</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun drop(n: Int): List<A> {</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> tailrec</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> fun recDrop(m: Int, xs: List<A>): List<A> {</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return if (m <= 0)</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> xs</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> else when(xs) {</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Nil -> xs</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Cons -> recDrop(m - 1, xs.tail())</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // recDrop</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return recDrop(n, this)</span></div>
<div class="MsoBodyText" style="text-align: justify;">
</div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">} // drop</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<br /></div>
</div>
<div style="text-align: justify;">
One of the benefits of immutable persistent data structures such as the custom <b>List</b> is the performance gains that can be provided by data sharing. Accessing the first element of a list is immediate. Removing the first element is equally fast. The extension function <b>drop</b> in the Kotlin standard library makes a new list from the original with the first <b>n</b> elements removed and copying the remainder into the new list.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial;"><b>Higher order functions over lists</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The custom <b>List</b> class includes a number of higher order functions. One of these is member function <b>map</b> which applies a transformation function to all the elements in a <b>List</b> delivering a new <b>List</b>:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val square: (Int) -> Int = {n -> n * n}</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val isEven: (Int) -> Boolean = {n -> (n % 2 == 0)}</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val list: List<Int> = ListF.of(1, 2, 3, 4, 5)</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(1, 4, 9, 16, 25), list.map(square))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(false, true, false, true, false), list.map(isEven))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(list.map(compose(isEven, square)), list.map(square).map(isEven))</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="font-family: inherit;">With
immutability there can be no side effects. If there are no side effects it is
much easier to reason about the correctness of the code. The code is then more predictable than its
wholly imperative equivalent.</span></span></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="font-family: inherit;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Immutable data
promotes a different programming approach. More emphasis is given to
transforming the data instead of in-place mutation of the data. A greater
emphasis on transformation can lead to more elegant, more modular and more
scalable solutions.</span><span style="font-family: "comic sans ms";"><o:p></o:p></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="line-height: 115%;"><span style="font-family: inherit;">The use of transformation is shown in the following example which determines the names of the given capital cities that have a population
that exceed one million. The two-stage solution is first to filter out those
cities with populations over one million, then obtain their names. The <b>val</b> bindings for <b>largeCities</b> and <b>nameLargeCities</b>
do precisely that. The <b>largeCities</b>
binding references a new <b>List</b> as does the binding for <b>nameLargestCities</b>. We
demonstrate in the next example how to avoid this.</span></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="line-height: 115%;"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">class City(val name: String, val population: Int)</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val capitals: List<City> = ListF.of(</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Amsterdam", 730000),</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Berlin", 3400000),</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Brussels", 450000),</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Lisbon", 670000),</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("London", 7000000),</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Madrid", 3000000),</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Paris", 2200000),</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Stockholm", 720000)</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun namesOfCitiesOver1M(cities: List<City>): List<String> {</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val largeCities: List<City> = cities.filter{city -> (city.population > 1000000)}</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> val nameLargeCities: List<String> = largeCities.map{city -> city.name}</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return nameLargeCities</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">}</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-size: x-small;"><span style="font-family: arial; line-height: 115%;"></span></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of("Berlin", "London", "Madrid", "Paris"), namesOfCitiesOver1M(capitals))</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="font-family: inherit;">The next example repeats the previous example. </span></span>In the function <b>citiesOver1M</b> the two functions <b>filter</b> and <b>map</b> are uncurried versions of the member functions <b>filter</b> and <b>map</b>. The <b>val</b> binding <b>largeCities</b> is a concrete version of <b>filter</b> that transforms a List<City> into a List<City>. It is achieved by first currying <b>filter </b>then flipping its arguments so that the predicate function is the first parameter. We then partially apply it with the required predicate. We do the same for the val binding for <b>cityNames</b>. The <b>namesOfCitiesOver1M</b> binding then composes these two by pipelining the filtering through the mapping. The pipelining is achieved by forward composing (<b>pipe</b>) the functions <b>largeCitiesC</b> and <b>cityNamesC</b> so that output of the former is input into the latter.<br />
<br /></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="line-height: 115%;"><span style="line-height: 115%;"><span style="font-family: inherit;">This
is sometime known as the <i>point-free
programming</i> style in which the function <b>namesOfCitiesOver1M</b> does not include any reference to its (<b>List</b>) argument, but is defined using <i>combinators</i> and function composition.</span></span></span></span></div>
<div style="text-align: justify;">
<span style="line-height: 115%;"><span style="line-height: 115%;"><span style="line-height: 115%;"><span style="font-family: inherit;"><br /></span></span></span></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">class City(val name: String, val population: Int)</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val capitals: List<City> = ListF.of(</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Amsterdam", 730000),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Berlin", 3400000),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Brussels", 450000),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Lisbon", 670000),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("London", 7000000),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Madrid", 3000000),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Paris", 2200000),</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> City("Stockholm", 720000)</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val filter: (List<City>, (City) -> Boolean) -> List<City> = List<City>::filter</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val map: (List<City>, (City) -> String) -> List<String> = {ls: List<City>, f: (City) -> String -> ls.map(f)}</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val largeCities: (List<City>) -> List<City> = flip(C2(filter))({city: City -> (city.population > 1000000)})</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val cityNames: (List<City>) -> List<String> = flip(C2(map))({city: City -> city.name})</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val namesOfCitiesOver1M: (List<City>) -> List<String> = largeCities pipe cityNames</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-size: x-small;"><span style="font-family: arial; line-height: 115%;"></span></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of("Berlin", "London", "Madrid", "Paris"), namesOfCitiesOver1M(capitals))</span></div>
<div style="text-align: justify;"><br /></div><div style="text-align: justify;">
Function composition as shown provides a powerful mechanism for structuring designs: programs are written as a pipeline of operations, passing the appropriate data structure between each operation. Here, we pipe a <b>List </b>from the <b>largestCities </b>operation through to the <b>cityNames </b>operation. A number of such operations would imply constructing temporary <b>List </b>objects and for large <b>List</b>s could prove an expensive process. A later blog from this series will investigate <b>Stream</b>s as an alternative structure.</div><div style="text-align: justify;"><br />
<span style="font-size: 14.6667px;">It is common to want to reduce a list to a single value. For example, we might wish to sum or multiply all the elements in a list. This is the basis for a particular kind of higher order function called <i>folding</i>. Folding is used to fold a function (such as a summation) into a list of values. Here are some simple examples:</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(10, ListF.of(1, 2, 3, 4).foldLeft(0){x -> {y -> x + y}})</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(0, ListF.empty<Int>().foldLeft(0){x -> {y -> x + y}})</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(500500, ListF.closedRange(1, 1000).foldLeft(0){x -> {y -> x + y}})</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.of(1, 2, 3, 4), ListF.of(1, 2, 3, 4).foldLeft(ListF.empty()){list -> {elem -> list.append(elem)}})</span></span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">Folding is a surprisingly fundamental operation. Its generality allows us to define many standard list processing operations. In the following example the <b>reverse </b>operation is defined in terms of a <b>foldLeft</b>:</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun <A> reverse(list: List<A>): List<A> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> list.foldLeft(ListF.empty(), flip(C2(ListF::cons)))</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.of(4, 3, 2, 1), reverse(ListF.of(1, 2, 3, 4)))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(ListF.of("Jessie", "John", "Ken"), reverse(ListF.of("Ken", "John", "Jessie")))</span></span><br />
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="font-family: arial; font-size: 14.6667px;"><b>Higher Order Abstractions</b></span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="font-size: 14.6667px;">Like the <b>Option </b>type, the <b>List </b>type is a functor (functions <b>fmap</b>, <b>distribute</b>, etc), an applicative functor (functions <b>ap</b>, <b>product2</b>, etc) and a monad (functions <b>bind</b> or <b>flatMap</b>). The following example demonstrates using function <b>fmap </b>on a <b>List</b>. Function <b>fmap </b>is defined in terms of the member function <b>map </b>described above.</span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(1, 4, 9, 16), ListF.of(1, 2, 3, 4).fmap{n -> n * n})</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val replicate: (Int) -> (Int) -> List<Int> = {n -> {x -> ListF.replicate(n, x)}}</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of(ListF.of(1, 1, 1), ListF.of(2, 2, 2), ListF.of(3, 3, 3), ListF.of(4, 4, 4)),</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of(1, 2, 3, 4).fmap(replicate(3))</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div>
<div style="font-size: 14.6667px;">
<br /></div>
<div style="font-size: 14.6667px;">
Function <b>fmap</b> is accompanied with the infix equivalent <b>dollar</b>. This allows us the to use the transformation function as the first parameter:</div>
<div style="font-size: 14.6667px;">
<br /></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers: List<Int> = ListF.of(1, 2, 3, 4)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(2, 3, 4, 5), {n: Int -> n + 1} dollar numbers)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(true, false, true, false), {n: Int -> (isEven(n))} dollar ({n: Int -> n + 1} dollar numbers))</span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="font-size: 14.6667px;">The following demonstrates how function <b>ap </b>draws every function from the parameter list and applies it to every value in the receiver list:</span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun mul(m: Int, n: Int): Int = m * n</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun add(m: Int, n: Int): Int = m + n</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun power(m: Int, n: Int): Int {</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> var pow: Int = 1</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> for (k in 1..n)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> pow = pow * m</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> return pow</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">}</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val mul0: (Int) -> Int = C2(::mul)(0)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val add100: (Int) -> Int = C2(::add)(100)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val pow2: (Int) -> Int = flip(C2(::power))(2)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(0, 0, 0, 101, 102, 103, 1, 4, 9), ListF.of(1, 2, 3).ap(ListF.of(mul0, add100, pow2)))</span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="font-size: 14.6667px;">The infix function <b>fmap</b> and <b>appliedOver </b>support presenting the logic in the <i>applicative style</i>:</span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers4: List<Int> = ListF.closedRange(1, 4)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val numbers6: List<Int> = ListF.closedRange(1, 6)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of(2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 10),</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> {m: Int -> {n: Int -> m + n}} fmap numbers4 appliedOver numbers6</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="font-size: 14.6667px;">This short example shows the monadic <b>bind </b>operation used with lists. The <b>bind </b>operation is also known as <b>flatMap</b>:</span></div>
<div>
<span style="font-size: 14.6667px;"><br /></span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(-1, 1, -2, 2, -3, 3), ListF.of(1, 2, 3).bind{n -> ListF.of(-n, n)})</span></div>
</div>
</div>
</div>
</div>
<br /><br /><br /><span style="font-family: arial;"><b>Foldables</b></span><br /><br /><div>Foldable type class instances can be defined for data structures that can be folded to a summary value. Most collection types have <b>foldLeft </b>and <b>foldRight </b>functions. A left fold on lists was presented earlier.</div><div><br /></div><div>Foldable provides us with a host of useful functions defined on top of <b>foldLeft </b>and <b>foldRight</b>. Many of these are facsimiles of familiar functions from the class: <b>find</b>, <b>exists</b>, <b>toList</b> and so on.</div><div><br /></div><div>In addition to these familiar functions, Dogs provides two functions that make use of <i>monoids</i>: function <b>fold</b> combines all elements in the list using their monoid; function <b>foldMap </b>maps a user-supplied function over the list and combines the results using a monoid:</div><div><br /></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(15, ListF.of(1, 2, 3, 4, 5).fold(intAddMonoid))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(13, ListF.of("Ken", "John", "Jessie").foldMap(intAddMonoid){str: String -> str.length})</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals("1223", ListF.of(1, 22, 3).foldMap(stringMonoid){n: Int -> n.toString()})</span></div><div><br /></div><div>The <b>intAddMonoid </b>is a monoid over <b>Int</b>s with zero as its identity element and addition as the binary operation. The first assert adds the <b>Int</b>s in the list to a start value zero. Function foldMap maps each element of the structure to a monoid, and combines the results. In the second assert we add the lengths of each string in the list. In the final assert each <b>Int</b> is converted to its string form then the strings are concatenated.</div></div></div><div style="text-align: justify;"><br /><br /><br /><span style="font-family: arial;"><b>Traversables</b></span><br /><br /><div>Traversable structures are collections of elements that can be operated upon with an <i>effectful visitor operation</i>. The visitor function performs a side-effect on each element and composes those side effects whilst retaining the original structure. Since Kotlin does not support higher-kinded types we have various traverse operations named after the effectful type to be used. For example, the function traverseOption has the signature:</div><div><br /></div><div>fun <A, B> List<A>.traverseOption(f: (A) -> Option<B>): Option<List<B>></div><div><br /></div><div>and traverses the <b>List</b>, applying the visitor function to every element and transforming each to an effectful <b>Option</b> type.</div><div><br /></div><div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> some(ListF.of(false, true, false, true)),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of(1, 2, 3, 4).traverseOption{ n: Int -> some(isEven(n)) }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: white; font-family: arial; font-size: x-small;"><br /></span></div><div><div><span style="background-color: white;">Sometimes you will be given a traversable that has effectful values already, such as a List<Option<A>>. </span><span style="background-color: white;">Since the values themselves are effects, traversing with identity will turn the traversable inside out. This is result of the <b>sequenceOption </b>operation:</span></div></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> some(ListF.of(1, 2, 3, 4)),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of(some(1), some(2), some(3), some(4)).sequenceOption()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> none(),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of(some(1), none(), some(3), some(4)).sequenceOption()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: white; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: white;">Here is the sequence operation with values of type <b>Either</b>:</span></div><div><span style="background-color: #cccccc; font-family: inherit;"><br /></span></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> right(ListF.of(1, 2, 3, 4)),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of<Either<String, Int>>(right(1), right(2), right(3), right(4)).sequenceEither()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("one"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of<Either<String, Int>>(left("one"), right(2), left("three"), right(4)).sequenceEither()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div></div></div><div><br /></div><div>We can now traverse structures that contain strings parsing them into integers and accumulating failures with <b>Either</b>:</div></div><div><br /></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun parseInt(str: String): Either<String, Int> =</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> try {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> right(Integer.parseInt(str))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } catch (ex: Exception) {</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("parseInt: string $str not a parsable integer")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> right(ListF.of(12, 34, 56)),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of("12", "34", "56").traverseEither{ str: String -> parseInt(str) }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> left("parseInt: string ab not a parsable integer"),</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> ListF.of("12", "ab", "56").traverseEither{ str: String -> parseInt(str) }</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">)</span></div></div><div><br /></div>
<br />
<br />
<span style="font-family: arial;"><b>Case Study</b></span><br />
<br />
We have seen the point-free style of programming as one in which functions do not identify the parameters on which they operate. Instead the definitions merely compose other function combinators. In this example we show a much more elaborate example. The solution is obtained by following the types when composing the functions. The solution is not optimal but demonstrates how such a development is followed.<br />
<br />
The <i>maximum segment sum</i> problem computes the maximum of the sums of all segments in a sequence of integers. A segment is a contiguous sub-sequence of the integers. The sequence -1, 2, -3, 5, -2, 1, 3, -2, -2, -3, 6 has maximum sum 7, the sum of the segment 5, -2, 1, 3.<br />
<br />
The problem is specified by:<br />
<br />
<span style="font-family: arial; font-size: x-small;">maximumSegmentSum = segments pipe mapSum pipe maximum</span><br />
<br />
where <b>segments </b>returns a list of all segments of a list with the type List<List<Int>>. The function <b>mapSum</b> computes the sum of each of the segments delivering a List<Int>. Function <b>maximum </b>then finds the greatest in this list.<br />
<br />
The function <b>segments </b>can be defined in a number of ways including:<br />
<br />
<span style="font-family: arial; font-size: x-small;">segments = tails pipe mapInits pipe concat</span><br />
<br />
where <b>tails </b>returns all the tail segments of a list. For example the <b>tails </b>of the list [1, 2, 3] is the nested list [[1, 2, 3], [2, 3], [3], []]. Function <b>mapInits </b>is then applied to this List<List<Int>>. Function <b>inits </b>is the counterpart to function <b>tails</b>. When <b>mapInits </b>is applied to the nested list produced from <b>tails </b>we get [[[], [1], [1, 2], [1, 2, 3]], [[], [2], [2, 3]], [[], [3]], []]. Finally, function <b>concat </b>flattens the nested list by one level producing [[], [1], [1, 2], [1, 2, 3], [], [2], [2, 3], [], [3]].<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val maximum: (List<Int>) -> Int = {list -> list.foldRight1{m -> {n -> max(m, n)}}}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val mapSum: (List<List<Int>>) -> List<Int> = {list -> list.map(List<Int>::sum)}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val mapInits: (List<List<Int>>) -> List<List<List<Int>>> = {list -> list.map(List<Int>::inits)}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val tails: (List<Int>) -> List<List<Int>> = {list -> list.tails()}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val concat: (List<List<List<Int>>>) -> List<List<Int>> = {list -> shallowFlatten(list)}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val segments: (List<Int>) -> List<List<Int>> = tails pipe mapInits pipe concat</span><br />
<span face=""arial" , "helvetica" , sans-serif">val maximumSegmentSum: (List<Int>) -> Int = segments pipe mapSum pipe maximum</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(7, maximumSegmentSum(ListF.of(-1, 2, -3, 5, -2, 1, 3, -2, -2, -3, 6)))</span></span></div>
<div><br /></div><div><br /></div><div><br /></div><span style="font-family: arial;"><b>Performance</b></span><div><br /></div><div style="text-align: justify;">Linked lists are extremely efficient for sequentially accessing elements from the head end or for adding elements to that head end. They are not designed for accessing elements by index or for some bulk operation like reversing a list.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Immutable and persistent linked lists are missing from Kotlin. As we have shown they are easy to implement and it would benefit Kotlin if they were provided as standard. They are much better for some use cases than what Kotlin offers. For example, adding an element in front of a non-modifiable list (kotlin.collections.List interface) is painful and extremely inefficient. Adding an element to the front raises many awkward questions: how should we do it?; should we use a mutable list?; what if we need to share the list or reuse it later?; and should we make defensive copies?</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Using a non-modifiable list as if it were immutable, or using a mutable list when you need an immutable one, can be more problematic than using an immutable, data sharing linked lists. In the following the first two asserts reveal that the <b>MutableList </b>member function <b>subList </b>returns a <i>view</i> of the portion of <b>mut </b>and any change to either <b>mut </b>or <b>sub </b>is reflected in the other. This is a consequence of <b>MutableList </b>having an <b>ArrayList</b> implementation. The solution would be to make a defensive copy of <b>sub</b> (which is slow) before changing the first element.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val mut: MutableList<Int> = mutableListOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val sub: MutableList<Int> = mut.subList(0, 4)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(mutableListOf(0, 1, 2, 3), sub)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">sub[0] = 99</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(mutableListOf(99, 1, 2, 3, 4, 5, 6, 7, 8, 9), mut)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun List<Int>.subList(from: Int, to: Int): List<Int> =</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> this.drop(from).take(to - from)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val list: List<Int> = ListF.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val subList: List<Int> = list.subList(0, 4)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(0, 1, 2, 3), subList)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val subList99: List<Int> = subList.update(0, 99)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(0, 1, 2, 3), subList)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(99, 1, 2, 3), subList99)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), list)</span></div></div><div><br /></div><div>The final four asserts demonstrate that immutable persistent linked lists are much safer and much more performant.</div><div><br /></div><div style="text-align: justify;">A benchmark comparing our immutable persistent linked list, Kotlin's non-modifiable list (read-only interface), Kotlin's mutable list and the <b>PersistentList </b>class from the Immutable Collections Library for Kotlin at [https://github.com/Kotlin/kotlinx.collections.immutable]. The timings measure (in ms) inserting 10000 new elements to the start of the collection:</div><div><br /></div><div>Insert 10000 elements to the start of our immutable/persistent <b>List</b>:<span> </span>0.5</div><div>Insert 10000 elements to the start of Kotlin's <b>MutableList </b>type:<span> </span>10.8</div><div>Insert 10000 elements to the start of Kotlin's <b>List </b>type:<span> </span><span> </span><span> </span><span> </span><span> </span><span> </span>435.3</div><div>Insert 10000 elements to the start of kotlinx <b>PersistentList </b>type:<span> </span><span> </span>291.2</div><div><br /></div><div>The table reveals how slow is Kotlin's non-modifiable <b>List </b>type.</div><div><br /></div><div>In the next table we show the timings to filter all the even valued integers from integer lists containing 1, 2, 3, ..., 10000. Our linked list is slower by a factor of 2.</div><div><br /></div><div>Filter all even-valued integers from our immutable/persistent <b>List</b>: 0.71</div><div>Filter all even-valued integers from Kotlin's <b>MutableList</b> type: 0.33</div><div>Filter all even-valued integers from Kotlin's <b>List</b> type: 0.33</div><div>Filter all even-valued integers from kotlinx <b>PersistentList</b> type: 0.29</div><div><br /></div><div style="text-align: justify;">The following table presents the timings to insert 10000 new elements to the end of a collection. Clearly, linked lists are not suited for operations of this type..</div><div><br /></div><div><div>Insert 10000 elements to the end of our immutable/persistent <b>List</b>: 1547.8</div><div>Insert 10000 elements to the end of Kotlin's <b>MutableList </b>type: <span> 0.4</span></div><div>Insert 10000 elements to the end of Kotlin's <b>List </b>type: 451.8</div><div>Insert 10000 elements to the end of kotlinx <b>PersistentList </b>type: 2.5</div></div><div><br /></div><div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">The code for the Dogs library can be found at:</div><div style="text-align: justify;"><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div></div><div><span style="color: black;"><br /></span></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-51936419374911169982020-05-21T06:45:00.002-07:002022-03-26T08:13:31.670-07:00Kotlin: Property Based Testing<b><span style="font-family: arial; font-size: large;">Kotlin: Property Based Testing</span></b><br />
<br />
<div style="text-align: justify;">
<i>In this blog we introduce property based testing, how it works, show where it might fit into your testing strategy, and walk you through building property based tests with the custom KwikCheck testing framework. In the follow-on blog we look at property based testing of immutable and persistent data structures and </i><i>property based testing of </i><i>stateful systems.</i></div>
<br />
<br />
<div style="text-align: justify;">
In traditional <i>unit testing</i>, you run your code with specific inputs and check that you get the expected outputs. This means you need to anticipate possible problematic inputs in advance. In the following illustration we unit test a newly developed <span style="font-family: inherit;"><b>sort </b></span>function by trying it with a list of mixed values; a list where the values are already in sort order; a list with duplicates present; a singleton list and an empty list. With the correct results produced we declare our function correct.</div>
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">sort([4, 2, 7, 3, 1]) == [1, 2, 3, 4, 7]</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">sort([1, 2, 3, 4, 7]) == [1, 2, 3, 4, 7]</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">sort([4, 2, 7, 2, 1]) == [1, 2, 2, 4, 7]</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">sort([7]) == [7]</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">sort([]) == []</span></span><br />
<br />
<div style="text-align: justify;">
One of the challenges of traditional unit testing is that it represents <i>example based testing</i>. Each unit test essentially establishes specific input data points, runs the code under test, and then checks the output. Writing many of these tests does not mean we will account for all possible behaviors. As the complexity of our software grows so does the probability that we will fail to account for a key scenario.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<i>Property-based testing</i> is a technique where your tests describe the properties and behavior you expect your code to have, and the testing framework tries to find inputs that violate those expectations. Rather than testing a function against specific inputs we try to reason about its behavior over a range of inputs.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Test properties are presented as logical propositions. For example, the <i>stack </i>data type is our standard last-in-first-out data store. Operation <b>push </b>injects a new element on to the stack top, while operation <b>top </b>delivers the item at the stack top. For all stack <b>st </b>and all element <b>el </b>the following proposition is a statement that affirms or denies the predicate:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;">top(push(el, st)) == el</span></div>
<br />
<div style="text-align: justify;">
We test this property embedded in a Unit test framework. The <b>forAll </b>function accepts a generator that produces a randomized stack containing randomized integer values, and a generator that delivers randomized integer values. The generated stack and the generated integer are captured in the lambda parameter to <b>forAll </b>as <b>st </b>and <b>el</b> respectively. Function <b>prop </b>expects a predicate for our logical proposition and wraps it into a <b>Property </b>instance. Function <b>check</b> then runs the test and delivers a <b>CheckResult </b>value which, since we are using a Unit test harness, we can complete with an assert.</div>
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun stackOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genStack(genInt), genInt) { st, el -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(st.push(el).top() == el)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> //assertTrue(checkResult.isPassed())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span><br />
</span><div>
<br /></div>
<div style="text-align: justify;">
However, for the purpose of this blog, it is more convenient to print the result from the function <b>summary</b>:</div>
<br />
<span style="background-color: white; font-family: arial; font-size: x-small;">OK, passed 100 tests</span><br />
<br />
which informs us that 100 (the default) tests were generated and that the property holds.<br />
<br />
<div style="text-align: justify;">
Property-based testing was popularized by the Haskell library QuickCheck. You specify properties of your code that should hold regardless of input. QuickCheck then randomly generates the input data to try to find a case for which the property fails. This form of testing became known as <i>property based testing</i> and is actually the principal form of testing in the Haskell ecosystem.</div>
<br />
<div style="text-align: justify;">
The KwikCheck test framework for Kotlin (as described here) is modeled after the QuickCheck framework. Property-based testing is <i>generative testing</i>. You do not supply specific example inputs with expected outputs as with unit tests. Instead, you define properties about the code and use the generative-testing engine to create randomized inputs to ensure the defined properties are correct. KwikCheck allows us to express these properties and generate the randomized inputs.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Automated test generation means, if you've got a function that operates on a particular input, you specify a property (or several properties) about that function, and then generators will give you variations on the input data to test the function, the edge cases, etc., and tell you whether the property holds. You can use the default generators for known types provided by KwikCheck, or define your own.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Test properties are presented as logical propositions. Examples include:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">!P || !Q == !(P && Q)</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">(S1 + S2).endsWith(S2)</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">L.reverse().reverse() == L</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: white; font-size: x-small;">L1.reverse().zip(L2.reverse()) == L1.zip(L2).reverse() // UNTRUE</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The first example is De Morgan's law which relates conjunctions and disjunctions of propositions through negation (where P and Q are boolean values). The second example claims that the concatenation of the strings S1 and S2 will end with the string S2. The third example specifies that if we reverse a list L then reverse the result it will deliver the original list. The fourth example, while untrue, can look correct especially if unit tested with a few examples. It involves zipping and reversing two lists.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here is how KwikCheck expresses the second example above:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;">@Test fun endsWithOperation() {</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"> val genStr1: Gen<String> = genString</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"> val genStr2: Gen<String> = genString</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"> val prop: Property = forAll(genStr1, genStr2){str1, str2 -></span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"> prop((str1 + str2).endsWith(str2))</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"> }</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"> val checkResult: CheckResult = prop.check()</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;"> println(checkResult.summary())</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;">}</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
with the output:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;">OK, passed 100 tests</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here is the fourth example above:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun reverseZipOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val genInt: Gen<Int> = choose(1, 10)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val genIntList: Gen<List<Int>> = genList(genInt)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val genAlpha: Gen<Char> = genAlphaUpperChar</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val genAlphaList: Gen<List<Char>> = genList(genAlpha)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genIntList, genAlphaList) { xs, ys -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(xs.reverse().zip(ys.reverse()) == xs.zip(ys).reverse())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<div>
<br /></div>
</div>
<div style="text-align: justify;">
It is, of course, a failing test and KwikCheck displays the counter-example:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;">Falsified after 4 passed tests with (<[10]>, <[C, R]>)</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
which informs us that four generated tests were initially successful but when tested with the two lists shown the property failed. The example is using the immutable and persistent <b>List </b>class from the custom library KData noted at the end of this article.<br />
<br />
Properties which are simple equations are conveniently represented by booleans. Many laws, however, only hold under certain conditions. KwikCheck provides an <b>implication </b>combinator to represent such conditionals. In the following the law that if m <= n then the max(m, n) is n:<br />
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun conditionalOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genInt, genInt){m, n -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> (m <= n) implies prop(max(m, n) == n)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<div>
<br /></div>
<div>
The output is:</div>
<div>
<br /></div>
<div>
<span style="font-family: arial; font-size: x-small;">OK, passed 100 tests (105 discarded)</span></div>
<div>
<br /></div>
<div>
and reveals the condition was not met on 105 occasions.</div>
<div>
<br /></div>
<div>
We can also combine existing properties into new ones using the <b>and </b>and <b>or</b> combinators. In the following we incorrectly define function <b>mul</b>. Three separate properties are combined to test the result from applying function <b>mul</b>.</div>
<div>
<br /></div>
<div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">@Test fun combiningOperation() {</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> fun mul(m: Int, n: Int): Int = m + n // ERROR</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val property = forAll(choose(1, 10), choose(101, 110)){m, n -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val res = mul(m, n)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(res >= m) and prop(res >= n) and prop(res < m + n)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val checkResult: CheckResult = property.check()</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> println(checkResult.summary())</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">}</span></div>
</div>
</div>
<div>
<br /></div>
<div>
This fails immediately with <b>m </b>= 3 and <b>n</b> = 108:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">Falsified after 0 passed tests with (3, 108)</span></div>
</div>
<div>
<br /></div>
<div>
Complex properties with many conditions can make it difficult to decide exactly what is wrong when a property fails. The next example repeats the previous example, labeling the individual properties. The output reveals the first test fails because the result does not sum.</div>
<div>
<div>
<br /></div>
<div>
<span style="font-family: arial; font-size: x-small;">@Test fun labellingOperation() {</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> fun mul(m: Int, n: Int): Int = m + n // ERROR</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val property = forAll(choose(1, 10), choose(101, 110)){m, n -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val res = mul(m, n)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(res >= m).label("res >= m") and</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(res >= n).label("res >= n") and</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(res < m + n).label("result not sum")</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val checkResult: CheckResult = property.check()</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> println(checkResult.summary())</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">}</span></div>
</div>
<div>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: inherit;">Output:</span></div>
<div>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span></div>
<div>
<div style="font-size: small;"><span style="font-family: arial;">
Falsified after 0 passed tests with (7, 109)</span></div>
<div style="font-size: small;"><span style="font-family: arial;">
Labels of failing property: result not sum</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">KwikCheck supports collecting statistics about the test data that has been generated during property evaluation. This is useful for inspecting test case generation and ensuring all cases are tested and not simply trivial ones. The next example operates on an ordered list and the property we check is that if the list is ordered then the <b>insert </b>function maintains that ordering.</span></div>
<div style="font-family: Arial, Helvetica, sans-serif; font-size: small;">
<br /></div>
<div style="font-size: small;">
<div><span style="font-family: arial;">
@Test fun collectSortedListOperation() {</span></div>
<div><span style="font-family: arial;">
fun insert(n: Int, list: List<Int>): List<Int> =</span></div>
<div><span style="font-family: arial;">
when (list) {</span></div>
<div><span style="font-family: arial;">
is List.Nil -> ListF.singleton(n)</span></div>
<div><span style="font-family: arial;">
is List.Cons -> if (n < list.head())</span></div>
<div><span style="font-family: arial;">
ListF.cons(n, list)</span></div>
<div><span style="font-family: arial;">
else</span></div>
<div><span style="font-family: arial;">
ListF.cons(list.head(), insert(n, list.tail()))</span></div>
<div><span style="font-family: arial;">
} // insert</span></div>
<div>
<span style="font-family: arial;"><br /></span></div>
<div><span style="font-family: arial;">
fun isOrdered(list: List<Int>): Boolean =</span></div>
<div><span style="font-family: arial;">
if (list.isEmpty())</span></div>
<div><span style="font-family: arial;">
true</span></div>
<div><span style="font-family: arial;">
else</span></div>
<div><span style="font-family: arial;">
list.zip(list.drop(1)).forAll{pr -> (pr.first <= pr.second)}</span></div>
<div>
<span style="font-family: arial;"><br /></span></div>
<div><span style="font-family: arial;">
val property = forAll(genInt, genList(genInt)){n, list -></span></div>
<div><span style="font-family: arial;">
isOrdered(list) implies prop(isOrdered(insert(n, list))).collect(list.size())</span></div>
<div><span style="font-family: arial;">
}</span></div>
<div><span style="font-family: arial;">
val checkResult: CheckResult = property.check(maxDiscarded = 10000)</span></div>
<div><span style="font-family: arial;">
println(checkResult.summary())</span></div>
<div><span style="font-family: arial;">
}</span></div>
</div>
<div style="font-family: Arial, Helvetica, sans-serif; font-size: small;">
<br /></div>
</div>
<div>
<span style="font-family: inherit;">Here, the property is not tested with large lists since they are all randomly generated. Lists of size 0, 1, 2, 3 and 4 have been tested. The output suggests we need a special <b>List </b>generator that generates large ordered lists.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">OK, passed 100 tests (3340 discarded)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">Collected test data:</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">42% 0</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">31% 1</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">19% 2</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">7% 3</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">1% 4</span></div>
<div style="font-family: inherit;">
<br /></div>
</div>
<div>
The <b>classify </b>combinator does not change the meaning of a property but classifies some of the test cases. Here, those lists with size greater than 5 are classified as large and the others classified as small.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">@Test fun classifyReverseListOperation() {</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val property = forAll(genList(genInt)) {list-></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(list.reverse().reverse() == list).classify(list.size() > 5, "large", "small")</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val checkResult: CheckResult = property.check(maxDiscarded = 10000)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> println(checkResult.summary())</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">}</span></div>
</div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">The output is:</span></div>
<div><br /></div><div>
<div>
<span style="font-family: arial; font-size: x-small;">OK, passed 100 tests</span></div>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">
</span>
<br />
<div>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">Collected test data:</span></div>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">
</span>
<br />
<div>
<span style="font-family: arial; font-size: x-small;">73% large</span></div>
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">
</span>
</span><div>
<span style="font-family: arial; font-size: x-small;">27% small</span></div>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">
<div>
<br /></div>
</span></div>
<div>
The core of the KwikCheck library comprises the classes <b>Gen<A></b> and <b>Property</b>. The class <b>Gen<A></b> is the generator class for values of type A. The class <b>Property </b>represents an algebraic property that may be checked for its truth. Its most important member function is <b>check </b>which delivers a result.</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Interestingly both the <b>Gen </b>and <b>Property </b>classes are immutable and have a single (different) function for their representation. Most member functions for these classes return a new instance with a composed function for its representation. The implementation functions for both <b>Gen </b>and <b>Property </b>do not execute until called by <b>check </b>in <b>Property</b>. Both classes use function representations in order to be <i>lazy</i>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
With KwikCheck you specify properties of your code that should hold regardless of input. KwikCheck then randomly generates the input data to try to find a case for which the property fails. In the following example we claim (incorrectly) that the largest example in a list of integers is the item at the front of the list.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun failingLargestOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> fun largest(list: List<Int>): Int = list.head()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genList(1, genInt)) { list -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(largest(list) == list.sort { a, b -> a.compareTo(b) }.last())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<div>
<br /></div>
</div>
<div style="text-align: justify;">
with the output:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;">Falsified after 6 passed tests with <[3, 5, 0]></span></div>
<br />
We then correct this in the next example with a correct definition for function <b>largest</b>.<br />
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun successfulLargestOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> fun largest(list: List<Int>): Int {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> fun biggest(list: List<Int>, big: Int): Int =</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> when (list) {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> is Nil -> big</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> is Cons -> if (list.head() > big)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> biggest(list.tail(), list.head())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> else</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> biggest(list.tail(), big)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> } // biggest</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> return biggest(list.tail(), list.head())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> } // largest</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genList(1, genInt)) { list -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(largest(list) == list.sort { a, b -> a.compareTo(b) }.last())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<div>
<br /></div>
with the output:<br />
<br />
<span style="background-color: white; font-family: arial; font-size: x-small;">OK, passed 100 tests</span><br />
<br />
<div style="text-align: justify;">
KwikCheck randomly generates the input data to try to find a case for which the property fails. When such a case is found, we can request it tries to find a minimal test case by <i>shrinking </i>the input data. This minimal test case is then reported for easy inspection. It will try to find smaller inputs that also violate the property, in order to give the developer a clearer message about the nature of the failure. The <b>List </b>class member function <b>removeDuplicates </b>removes duplicates from a list retaining the first of each occurrence. In this example we claim that removing all duplicates returns the same list which, of course, is false:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun failingRemoveDuplicatesOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val genIntList: Gen<List<Int>> = genList(genInt)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genIntList) {list -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(list.removeDuplicates() == list)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<div>
<br /></div>
</div>
<div style="text-align: justify;">
with the output:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: arial; font-size: x-small;">Falsified after 6 passed tests with <[3, 4, -4, 3, 3, -2]></span></div>
<br />
<div style="text-align: justify;">
While large inputs may produce the errors, KwikCheck will attempt to shrink the input sequence to the smallest possible that will reproduce the error. The smaller the input, the easier it is to fix. The next example repeats the same false claim but requests that the list should be shrunk to a more manageable size.</div>
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun shrinkingRemoveDuplicatesOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val genIntList: Gen<List<Int>> = genList(genInt)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val shrinkIntList: Shrink<List<Int>> = shrinkList(shrinkInt)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genIntList, shrinkIntList) { list -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(list.removeDuplicates() == list)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<div>
<br /></div>
with output:<br />
<br />
<span style="background-color: white; font-family: arial; font-size: x-small;">Falsified after 8 passed tests with <[0, 0]></span><br />
<br />
where it is now clear if we remove one of the duplicates the resulting list cannot be the same as this list with two zeros.<br />
<br />
<div style="text-align: justify;">
KwikCheck supports defining custom shrinking functions. We define a function that returns a Shrink<A> instance. The <b>shrink </b>factory method is used for this purpose. It expects a single function parameter with an A for its argument and returns a List<A>. An example is the library function <b>shrinkPair</b>:</div>
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">fun <A, B> shrinkPair(sa: Shrink<A>, sb: Shrink<B>): Shrink<Pair<A, B>> =</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> shrink{pair: Pair<A, B> -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> sa.shrink(pair.first).map{a: A -> Pair(a, pair.second)}.append(sb.shrink(pair.second).map{b: B -> Pair(pair.first, b)})</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span></span><br />
<br />
<div style="text-align: justify;">
KwikCheck supports creating custom generators. The following example declares the domain model class <b>Account </b>representing a bank account with account number and account balance. The class is immutable and both member functions deliver new instances. Function <b>credit</b> increases the balance by the amount. Function <b>debit </b>only reduces the balance provided it does not become negative.</div>
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">@Test fun domainModelGeneratorOperation() {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> class Account(val number: String, val balance: Int) {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> fun credit(amount: Int): Account = Account(number, balance + amount)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> fun debit(amount: Int): Account = Account(number, if (balance >= amount) balance - amount else balance)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"><br /></span>
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val genAccount: Gen<Account> = genAlphaNumStr.bind{number -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> genPosInt.bind{balance -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> value(Account(number, balance))</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val property = forAll(genAccount, genPosInt) { account, amount -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(account.debit(amount).balance >= 0)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> println(checkResult.summary())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span></span><br />
<div>
<br /></div>
with output:<br />
<br />
<span style="background-color: white; font-family: arial; font-size: x-small;">OK, passed 100 tests</span><br />
<br />
<div style="text-align: justify;">
The property we are checking is that all <b>debit </b>operations leave the balance positive. We establish the value binding <b>genAccount </b>for a generator Gen<Account> that delivers a random <b>Account </b>instance. It is common to implement such generators using the <i>monadic </i>features of the <b>Gen </b>class. Using the generator <b>genAlphaNumStr </b>we <i>bind </i>what it delivers to the lambda parameter <b>number</b>. Similarly, using the <b>genPosInt </b>generator we bind what it delivers to the lambda parameter <b>balance</b>. Using these two random values we produce the required random <b>Account</b>.<br />
<br />
<span face=""arial" , "helvetica" , sans-serif"><b>Case Study</b></span><br />
<br />
A common business use-case is validating a user login or a user registration. In the latter we might require the user to provide a name and an age. Both values might be supplied by entering values into text fields that populate a <b>Form </b>class:<br />
<br />
<span style="font-family: arial; font-size: x-small;">data class Form(val name: String, val age: Int)</span><br />
<br />
The validation logic is provided by the function:<br />
<br />
<span style="font-family: arial; font-size: x-small;">fun validateForm(form: Form): ValidationNel<Error, User></span><br />
<br />
which accepts a <b>Form </b>as parameter and returns a <b>ValidationNel </b>value. The <b>ValidationNel </b>type is an alias for the class <b>Validation</b>:<br />
<br />
<span style="font-family: arial; font-size: x-small;">typealias ValidationNel<E, A> = Validation<NonEmptyList<E>, A></span><br />
<br />
where the type parameter <b>E </b>represents failure and the type parameter <b>A </b>represents a successfully validated value. Failures are accumulated into a <b>NonEmptyList </b>when combining multiple <b>Validation </b>values using an <i>applicative style</i>.<br />
<br />
If the <b>Form </b>is valid function <b>validateForm </b>returns a <b>User</b> object:<br />
<br />
<span style="font-family: arial; font-size: x-small;">data class User(val name: String, val age: Int)</span><br />
<br />
If the <b>Form </b>is invalid <b>validateForm</b> returns a non-empty list of <b>Error </b>values:<br />
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">sealed class Error {</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> data class NameTooLong(val text: String) : Error()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> data class NameTooShort(val text: String) : Error()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> data class AgeTooLow(val num: Int) : Error()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> data class AgeTooHigh(val num: Int) : Error()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">} // Error</span></span><br />
<div>
<br /></div>
To develop some property tests we will need to generate a random form. In the first test we produce a valid form by generating a valid name and a valid age. A valid user name is an alphanumeric string of 3 to 30 characters. A valid age is an integer between 18 and 100 inclusive.<br />
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">val genValidName: Gen<String> = genAlphaNumStr(3, 30)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">val genValidAge: Gen<Int> = choose(18, 100)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">val genValidForm: Gen<Form> = form fmap genValidName ap genValidAge</span></span><br />
<div>
<br />
An applicative style (see both the Option and Validation blogs) is used to generate the valid form from the valid name and valid age and where <b>form </b>is a curried variant of the <b>Form </b>class constructor:<br />
<br />
<span style="font-family: arial; font-size: x-small;">val form: (String) -> (Int) -> Form = { name -> { age -> Form(name, age) }}</span><br />
<br /></div>
The test on valid data is:<br />
<br />
<span style="font-family: arial;"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">val property = forAll(genValidForm){form -></span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> val validation: ValidationNel<Error, User> = validateForm(form)</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> prop(validation.isSuccess())</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">}</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">val checkResult: CheckResult = property.check()</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">println(checkResult.summary())</span></span><br />
<div>
<br /></div>
<div>
producing the usual <span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">OK, passed 100 tests</span>.</div>
<div>
<br /></div>
<div>
We might also run tests with incorrect data. For example we might produce a form with an incorrect user name:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">val genInvalidName: Gen<String> = genAlphaNumStr(50)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">val genInvalidNameForm: Gen<Form> = form fmap genInvalidName ap genValidAge</span></div>
</div>
<div>
<br /></div>
<div>
Here the user name is any string of length 0 up to length 50. Both extremes are outwith our legal limits of 3 to 30 inclusive and function <b>validateForm </b>will fail.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">val property = forAll(genInvalidNameForm){form -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val validation: ValidationNel<Error, User> = validateForm(form)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val ok: Boolean = when (validation) {</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> is FailureNel<Error, User> -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> (validation.value.size() == 1) && isNameError(validation.value.head())</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> is SuccessNel<Error, User> -> true</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(ok)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">}</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">val checkResult: CheckResult = property.check()</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">println(checkResult.summary())</span></div>
</div>
<div>
<br /></div>
<div>
The proposition we check is determined by the <b>ok </b>value. If the validation is a <b>SuccessNel </b>then the property is true. If the validation is a <b>FailureNel </b>then we assert the <b>NonEmptyList </b>has size 1 and that single entry is a name error:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">fun isNameError(error: Error): Boolean =</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> when (error) {</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> is Error.NameTooLong -> true</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> is Error.NameTooShort -> true</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> else -> false</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> }</span></div>
</div>
<div>
<br /></div>
<div>
A test on a form with a valid name but an invalid age follows the same pattern.</div>
<div>
<br /></div>
<div>
In the next test we provide a form with both the name and the age invalid:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">val property = forAll(genInvalidNameAgeForm){form -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val validation: ValidationNel<Error, User> = validateForm(form)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val ok: Boolean = when (validation) {</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> is FailureNel<Error, User> -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> (validation.value.size() <= 2) && validation.value.forAll{error -> isNameError(error) || isAgeError(error)}</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> is SuccessNel<Error, User> -> true</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(ok)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">}</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">val checkResult: CheckResult = property.check()</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">println(checkResult.summary())</span></div>
</div>
<div>
<br /></div>
<div>
if the validation is a failure we may have accumulated one or two errors: a valid name but an invalid age; an invalid name but a valid age; or an invalid name and invalid age. If the validation is a <b>FailureNel </b>then we assert the list has size 1 or 2 and that the list elements are name or age errors.</div>
<div>
<br /></div>
<div>
A variation of this use case is one in which the users birth date is used instead of their age. The <b>Form </b>and the <b>User </b>have <b>Calendar </b>properties:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">data class Form(val name: String, val birthDate: Calendar)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">data class User(val name: String, val birthDate: Calendar)</span></div>
</div>
<div>
<br /></div>
<div>
The validation function is modified as:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">fun validateForm(today: Calendar, form: Form): ValidationNel<Error, User> =</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> user fmap validateName(form.name) ap validateAge(today, form.birthDate)</span></div>
</div>
<div>
<br /></div>
<div>
with today's date provided so we can validate the age from the birth date in the form.</div>
<div>
<br /></div>
<div>
The test appears below. Today's date is generated from the overloaded <b>choose </b>function with the start and end of the period. The randomly generated form is produced with a valid name and a valid birth date.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">val property = forAll(choose(GregorianCalendar(1900, 1, 1), GregorianCalendar(2099, 12, 31))){today -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> forAll(form fmap genValidName ap genValidBirthDate(today)){form -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val validation: ValidationNel<Error, User> = validateForm(today, form)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> prop(validation.isSuccess())</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">}</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">val checkResult: CheckResult = property.check()</span></div>
<div>
<span style="font-family: arial; font-size: x-small;">println(checkResult.summary())</span></div>
</div>
<div>
<br /></div>
<div>
To generate a valid birth date we must know today's date then generate a date that is 18 to 100 years earlier matching our initial requirements.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: arial; font-size: x-small;">fun genValidBirthDate(today: Calendar): Gen<Calendar> =</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> choose(18, 100).map{n -></span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val calendar: Calendar = today.clone() as Calendar</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> val year: Int = calendar.get(YEAR)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> calendar.set(YEAR, year - n)</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> calendar</span></div>
<div>
<span style="font-family: arial; font-size: x-small;"> } // genValidBirthDate</span></div>
</div>
<div>
<br /></div><div><br /></div><div><br /></div></div>
The KwikCheck sources are at []<div>The Dogs sources are at []<br /><br /></div><div><div><span color="rgba(0, 0, 0, 0.52)" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif" style="background-color: white; font-size: 14px;">Ken Barclay</span></div><div><br style="text-align: justify;" /></div></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-27827848403854272542020-05-19T06:29:00.010-07:002022-11-04T07:29:36.818-07:00Kotlin: Option type<span style="font-family: arial; font-size: large;"><b>Kotlin: Option type</b></span><br />
<br />
<div style="text-align: justify;">
<i>In this blog we consider how to deal with optional data - absent values that are not the result of an error. </i><i>This might happen when a function returns null when not expected. </i><i>A value of null is often used to represent an absent value. We can avoid using null by providing a type for representing optional values: the Option<A> class. The class is included in the custom library <b>Dogs</b>.</i></div>
<br />
<br />
<div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Kotlin
treats <b>null</b> in a special way so that
we may work safely with values that might be <b>null</b>. For instance, the null-safe operator for accessing properties
foo?.bar?.baz will not throw an exception if either <b>foo</b> or its <b>bar</b> property
is <b>null</b>, instead directly returning <b>null</b>.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Another approach to this problem is
to provide a type for representing optional values. Values that may be present
or absent are supported by the <b style="mso-bidi-font-weight: normal;">Option<A></b> sealed class. <b style="mso-bidi-font-weight: normal;">Option<A></b>
is a container for an optional value of type <b>A</b>. If the value of type <b>A</b> is present, then the <b style="mso-bidi-font-weight: normal;">Option<A></b>
is an instance of <b style="mso-bidi-font-weight: normal;">Some<A></b>
containing the value of type <b>A</b>. If
the value is absent, then the <b style="mso-bidi-font-weight: normal;">Option<A></b>
is an instance of <b style="mso-bidi-font-weight: normal;">None</b>.<o:p></o:p></span></div>
<br />
<div style="text-align: justify;">
You create an Option<String> for a given value by instantiating an instance of the <b>Some </b>class with the <b>some </b>factory function:</div>
<br />
<span style="font-family: arial; font-size: x-small;">val greeting: Option<String> = some("Hello Ken")</span><br />
<br />
<div style="text-align: justify;">
If you know the value is absent, you assign the <b>None </b>object through the <b>none </b>factory function:</div>
<br />
<span style="font-family: arial; font-size: x-small;">val goodbye: Option<String> = none()</span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">The
<b>Option</b> sealed class is shown below. It is an algebraic data type. The member function <b>isEmpty</b> returns <b>true</b> for <b>None</b> and <b>false</b> for
instances of <b>Some</b>. The function <b>filter</b> returns the receiver if it is <b>Some </b>and the predicate applied to this value; otherwise, returns <b>None</b>. The function <b>fold </b></span><span style="font-family: inherit;">returns the result of applying the first function </span><span style="font-family: inherit;">if the option is empty; otherwise return the second function applied to the wrapped value.</span></div>
<div style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<span style="font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">sealed class Option<A> {</span><br />
<span face=""arial" , "helvetica" , sans-serif"><span face=""arial" , "helvetica" , sans-serif"><br /></span><span></span><span face=""arial" , "helvetica" , sans-serif"> object None : Option<Nothing>()</span><span face=""arial" , "helvetica" , sans-serif"><br /></span><span></span><span face=""arial" , "helvetica" , sans-serif"> class Some<out A> internal constructor(val value: A) : Option<A>()</span><br /></span>
<span face=""arial" , "helvetica" , sans-serif"><br /></span></span></div><div><span style="font-family: arial; font-size: x-small;"> abstract fun isEmpty(): Boolean</span></div><div><span style="font-family: arial; font-size: x-small;"><span><br /></span>
<span face=""arial" , "helvetica" , sans-serif"> fun contains(predicate: (A) -> Boolean): Boolean</span><br />
<span face=""arial" , "helvetica" , sans-serif"> fun filter(predicate: (A) -> Boolean): Option<A> </span><br />
<span face=""arial" , "helvetica" , sans-serif"> fun <B> fold(none: () -> B, some: (A) -> B): B </span><br />
<span face=""arial" , "helvetica" , sans-serif"> fun <B> map(f: (A) -> B): Option<B> </span></span></div><div><span style="font-family: arial; font-size: x-small;"><span> fun <B> option(defaultValue: B, f: (A) -> B): B<br /></span>
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif"> // ...</span><span face=""arial" , "helvetica" , sans-serif"><br /></span>
<br />
<span face=""arial" , "helvetica" , sans-serif">} // Option</span></span><br />
<div>
<br /></div>
<div>
A number of contravariant functions are also defined as extension functions:</div>
<div>
<br /></div>
<div>
<span style="font-family: arial; font-size: x-small;">fun <A> Option<A>.getOrElse(defaultValue: A): A</span></div>
<div>
<br /></div>
<div>
The <b>getOrElse </b>function uses a default value in case an optional value is absent:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(5, some(5).getOrElse(99))</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(99, none<Int>().getOrElse(99))</span></div>
</div>
<div>
<br /></div><div style="text-align: justify;">The <b>option </b>member function takes a default value and a function as parameters. If the receiver value is <b>None </b>then the <b>defaultValue </b>is returned. Otherwise, the function is applied to the value wrapped in the <b>Some </b>and returns the result. In the following the default value is zero and the increment is the transformer function.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(0, none<Int>().option(0){n -> 1 + n})</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(5, some(4).option(0){n -> 1 + n})</span></div><div><br /></div><div>The generic type parameter <b>B </b>used in the declaration for the <b>option </b>function is a simple <b>Int </b>type in the above example. However, it might be a more complex type such as a <b>List</b> type. This is shown in the next example:</div><div><br /></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.empty(), none<Int>().option(ListF.empty()){n -> ListF.of(-n, n)})</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(ListF.of(-4, 4), some(4).option(ListF.empty()){n -> ListF.of(-n, n)})</span></div></div><div><br /></div><div>The default is the empty <b>List </b>and the transformer parameter converts the value wrapped in a <b>Some </b>into a <b>List </b>of the value and its negative.</div><div><br /></div><div>Of course, the type parameter <b>B </b>might be something more exotic such as a function type. In the following the default is the function <b>isEven </b>and the transformer is the curried binary function <b>same</b>. When the receiver is a <b>Some </b>it must wrap a <b>String </b>so that <b>same</b> can be called with the <b>String</b>. The resulting function expects an <b>Int </b>parameter and returns a <b>Boolean </b>that is true if the <b>Int </b>equals the string length.</div><div><br /></div><div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun isEven(n: Int): Boolean = (n % 2 == 0)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val same: (String) -> (Int) -> Boolean = {str -> {n -> (str.length == n)}}</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val op1: Option<String> = none()</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val op2: Option<String> = some("ken")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val op3: Option<String> = some("immutable")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(false, op1.option(::isEven, same)(3))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(true, op2.option(::isEven, same)(3))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(false, op2.option(::isEven, same)(4))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(true, op3.option(::isEven, same)(9))</span></div></div><div><br /></div><div>Observe how the <b>Option </b>type is declared as an abstract sealed class with two internal sub-types representing the absence and the presence of data. The absence of data is captured by the object <b>None </b>while the presence of data is represented by the subclass <b>Some</b>. The <b>Some </b>constructor is tagged as <b>internal </b>so values are only produced through the factory function <b>some</b>.</div></div>
<div style="text-align: justify;">
<br /></div>
<div>
<span style="font-family: arial; font-size: x-small;">val op: Option<Int> = Some(5) // cannot access Some constructor on right hand side</span></div>
<div>
<br />
<br />
<br />
<span style="font-family: arial;"><b>Pattern matching</b></span><br />
<br /></div>
<div style="text-align: justify;">
Neither the object <b>None </b>nor the class <b>Some </b>are tagged as <b>internal </b>or <b>private</b>. That way the type names can be used in user-defined functions:</div>
<div style="text-align: justify;">
<br /></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun <A> contains(op: Option<A>, predicate: (A) -> Boolean): Boolean =</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> when (op) {</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Option.None -> false</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> is Option.Some -> predicate(op.value)</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"> } // contains</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(true, contains(some(4)){n -> isEven(n)})</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(false, contains(none<Int>()){n -> isEven(n)})</span></div>
</div>
<div>
<br />
<br />
<br />
<span style="font-family: arial;"><b>Selected Option operations</b></span><br />
<br /></div>
<div style="text-align: justify;">
One important function of the <b>Option </b>class is the member function <b>map</b>. The function <b>map </b>applies the transforming function parameter converting an Option<A> into an Option<B>:</div>
<div style="text-align: justify;">
<br /></div>
<div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(true), some(4).map{n -> isEven(n)})</span></div>
<div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(none(), none<Int>().map{n -> isEven(n)})</span></div>
<div>
<span style="font-family: inherit; text-indent: 36pt;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: inherit; text-indent: 36pt;">The <b>Option </b>type is like a
container with zero or one elements. The higher order function </span><b style="font-family: inherit; text-indent: 36pt;">bind</b><span style="font-family: inherit; text-indent: 36pt;"> is used to make the </span><b style="font-family: inherit; text-indent: 36pt;">Option</b><span style="font-family: inherit; text-indent: 36pt;"> class into a </span><i style="font-family: inherit; text-indent: 36pt;">monad</i><span style="font-family: inherit; text-indent: 36pt;">. </span><span style="background: white; color: #222222; font-family: inherit; text-indent: 36pt;">A
monad is a way to structure computations in terms of values
and sequences of computations using those values. Monads allow the programmer
to build up computations using sequential building blocks, which can themselves
be sequences of computations. The monad determines how combined computations
form a new computation and frees the programmer from having to code the
combination manually each time it is required. It is useful to think of a monad
as a strategy for combining computations into more complex computations.</span></div>
<div style="text-align: justify;">
<span style="background-color: white; color: #222222; font-family: inherit; text-indent: 36pt;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: white; color: #222222; font-family: inherit; text-indent: 36pt;">The example below demonstrates how we might
use the monadic <b>Option </b>type. Running the program with the inputs 18, 27 and 9
delivers the result Some(Pair(2, 3)), demonstrating that 18 and 27 are exactly
divisible by 9. The inputs 18, 27 and 6 produce the result </span><b style="background-color: white; color: #222222; font-family: inherit; text-indent: 36pt;">None</b><span style="background-color: white; color: #222222; font-family: inherit; text-indent: 36pt;">, showing
that 18 and 27 are not both exactly divisible by 6:</span></div>
</div>
<div style="text-align: justify;">
<span style="background-color: white; color: #222222; font-family: inherit; text-indent: 36pt;"><br /></span></div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun divide(num: Int, den: Int): Option<Int> =<br /> if (num % den != 0) none() else some(num / den)<br /><br /> fun division(a: Int, b: Int, c: Int): Option<Pair<Int, Int>> =<br /> divide(a, c).bind{ac -> divide(b, c).bind{bc -> some(Pair(ac, bc))}}<br /><br />assertEquals(some(3), divide(12, 4))<br />assertEquals(none(), divide(12, 5))<br /><br />assertEquals(some(Pair(2, 3)), division(18, 27, 9))<br />assertEquals(none(), division(18, 27, 6))</span></div>
<div>
<br /></div>
<div>
<div style="text-align: justify;">
The monadic <b>Option </b>is supported by the <b>bind </b>(or <b>flatMap</b>) member function. Its signature is:</div>
</div>
<div>
<br /></div>
<div>
<span style="font-family: arial; font-size: x-small;">fun <B> bind(f: (A) -> Option<B>): Option<B></span></div>
<div>
<br /></div>
<div>
<div style="text-align: justify;">
A monad <i>fails fast</i>. If any of the <b>Option </b>values in a sequence of <b>bind</b>s is a <b>None </b>then the result is a <b>None</b>. In function <b>division </b>if the function call divide(a, c) delivers a <b>None </b>then processing is complete and <b>None </b>is returned. This means that the function call divide(b, c) is short-circuited and never executed.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Our goal is to stop computation if an error (<b>None</b>) is obtained. In other words fail-fast. Sometime we may want to accumulate all errors, for example when validating user input, but this is a different problem and leads to a different solution discussed below.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The <b>Option </b>type is also a <i>functor</i>, supporting the extension function <b>fmap </b>which simply repeats the <b>map </b>function. The <b>Option</b> type then represents something that can be mapped over.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial; font-size: x-small;">fun <A, B> Option<A>.fmap(f: (A) -> B): Option<B> = this.map(f)</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The inclusion of function <b>fmap </b>gives rise to a number of useful utilities that can be defined by it. Function <b>distribute</b>, for example,<b> </b>is applied to a pair wrapped in an <b>Option</b> and distributes the values into a pair of <b>Option</b>s:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial; font-size: x-small;">fun <A, B> Option<Pair<A, B>>.distribute(): Pair<Option<A>, Option<B>></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here is a simple illustration:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial; font-size: x-small;">assertEquals(Pair(some("Ken"), some(25)), some(Pair("Ken", 25)).distribute())</span></div>
<div style="text-align: justify;">
<span style="font-family: arial; font-size: x-small;">assertEquals(Pair(none(), none()), none<Pair<String, Int>>().distribute())</span></div>
<div style="text-align: justify;">
<br />
<br />
<br />
<span style="font-family: arial;"><b>Option composition</b></span><br />
<br /></div>
<div style="text-align: justify;">
The immutable <b>List </b>class from the custom library supports the extension function <b>sequenceOption </b>that combines a List<Option<A>> into an Option<List<A>>. It delivers a Some<List<A>> if all the values in the original list are <b>Some </b>instances. If there is at least one <b>None </b>in the list then the function delivers a <b>None</b>. The signature for <b>sequenceOption </b>is:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial; font-size: x-small;">fun <A> List<Option<A>>.sequenceOption(): Option<List<A>></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Composing the various <b>Option </b>functions we can sum the integer values in the list of <b>Option</b>s:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 10,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ListF.of(some(1), some(2), some(3), some(4)).sequenceOption().map{list -> list.sum()}.getOrElse(0)</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 0,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ListF.of(some(1), some(2), none(), some(4)).sequenceOption().map{list -> list.sum()}.getOrElse(0)</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The <b>Option </b>type is also an <i>applicative functor</i>. When mapping functions over the <b>Option </b>functor with <b>fmap </b>we have provided a unary function for the mapping as in some(6).fmap{m: Int -> isEven(m)}. What do we get if we provide a curried binary function? For example, what type is some(6).fmap{m: Int -> {n: Int -> (m == n)}}? The answer is we get a unary function wrapped in an <b>Option </b>as shown for the value binding <b>opF</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(6), some(5).fmap{m: Int -> m + 1})</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val opF: Option<(Int) -> Boolean> = some(6).fmap{m: Int -> {n: Int -> (m == n)}}</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(11), some(5).ap(some(6).fmap{m: Int -> {n: Int -> m + n}}))</span></div>
<div style="text-align: justify;">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(11), {m: Int -> {n: Int -> m + n}} fmap some(5) appliedOver some(6))</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
We cannot map a function wrapped in an <b>Option </b>over another <b>Option</b>. The <b>Option </b>type as an applicative functor includes the extension function <b>ap</b>:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: arial; font-size: x-small;">fun <A, B> Option<A>.ap(f: Option<(A) -> B>): Option<B></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
which applies the wrapped function to the receiver <b>Option</b>. This is shown in the assertion immediately following the <b>opF </b>binding. The infix version of <b>ap</b> is known as <b>appliedOver </b>and lets us express our intention in an <i>applicative style</i> as shown in the final assertion.</div>
</div>
<div>
<br />
<br />
<br />
<span style="font-family: arial;"><b>Case Study</b></span><br />
<br />
<div style="text-align: justify;">
The final illustration demonstrates how to use an <b>Option </b>to change how we might use a Kotlin <b>Map</b>. In the listing the function <b>get </b>returns an <b>Option</b> when querying for a given key. The standard implementation of Map.get(key) returns <b>null </b>if the key is absent.</div>
<div style="text-align: justify;">
<br /></div>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">data class User(val name: String, val email: String)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">fun <K, V> get(key: K, map: Map<K, V>): Option<V> {</span><br />
<span face=""arial" , "helvetica" , sans-serif"> val v: V? = map.get(key)</span><br />
<span face=""arial" , "helvetica" , sans-serif"> return if (v == null) none() else some(v)</span><br />
<span face=""arial" , "helvetica" , sans-serif">}</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val staff: Map<String, User> = mapOf(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "ken" to User("KenB", "ken@gmail.com"),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "john" to User("JohnS", "john@gMail.com"),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "jessie" to User("JessieK", "jessie@gmail.com")</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(some(User("KenB", "ken@gmail.com")), get("ken", staff))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(some("ken@gmail.com"), get("ken", staff).bind{user -> some(user.email)})</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(none(), get("Irene", staff))</span></span><br />
<br />
<div style="text-align: justify;">
The code sample demonstrates how functions returning an <b>Option </b>can be composed. You do not have to test for <b>None </b>occurring and we do not risk throwing a <b>NullPointerException</b>.</div>
<br />
<div style="text-align: justify;">
Suppose we are using <b>Option</b> to work with the results of look ups in two <b>Map</b>s. If we simply need to combine the results from two independent look ups we can use the applicative <b>fmap2 </b>function:</div>
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val departments: Map<String, String> = MapF.of( // department indexed by employee</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "Ken" to "Software",</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "John" to "Software",</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "Jessie" to "Database"</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif">val salaries: Map<String, Int> = MapF.of( // salaries indexed by employee</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "Ken" to 45000,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "John" to 40000,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "Jessie" to 45000</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val op: Option<Pair<String, Int>> = fmap2(departments.lookUpKey("Jessie"), salaries.lookUpKey("Jessie")){</span><br />
<span face=""arial" , "helvetica" , sans-serif"> dept, salary -> Pair(dept, salary)</span><br />
<span face=""arial" , "helvetica" , sans-serif">}</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(some(Pair("Jessie", 45000)), op)</span></span><br />
<br />
<div style="text-align: justify;">
Here we are performing two look ups but they are independent and we merely want to combine their results within the <b>Option </b>context. If we want the result of one look up to effect what look up we perform next then we need <b>bind </b>as shown next:</div>
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val ids: Map<String, Int> = MapF.of(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "Ken" to 123,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "John" to 456,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> "Jessie" to 789</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif">val departments: Map<Int, String> = MapF.of(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 123 to "Software",</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 456 to "Software",</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 789 to "Database"</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif">val salaries: Map<Int, Int> = MapF.of(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 123 to 45000,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 456 to 40000,</span><br />
<span face=""arial" , "helvetica" , sans-serif"> 789 to 45000</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val op: Option<Pair<String, Int>> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ids.lookUpKey("Jessie").bind{id: Int -></span><br />
<span face=""arial" , "helvetica" , sans-serif"> fmap2(departments.lookUpKey(id), salaries.lookUpKey(id)) {</span><br />
<span face=""arial" , "helvetica" , sans-serif"> dept, salary -> Pair(dept, salary)</span><br />
<span face=""arial" , "helvetica" , sans-serif"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif"> }</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(some(Pair("Database", 45000)), op)</span></span><br />
<br />
<div style="text-align: justify;">
Here <b>ids </b>is a <b>Map </b>between the employee name and employee id. To access Jessie's department and salary we first need to resolve Jessie's name to her id and then use this id to perform look ups in both <b>departments </b>and <b>salaries</b>.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial;"><b>Combining options</b></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Adopting the <b>Option </b>type may seem to make existing code obsolete. An existing code base may include many functions that convert some type A into some type B. Working with the <b>Option </b>type might suggest that we need functions from Option<A> to Option<B>. We can easily adapt the existing code base by using the custom library function <b>lift </b>from the object declaration <b>OptionF</b>:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun <A, B> lift(f: (A) -> B): (Option<A>) -> Option<B></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In the following <b>liftLength </b>lifts a function from a <b>String </b>to an <b>Int </b>into a function from an Option<String> to an Option<Int>. Similarly, <b>liftParseOct</b> lifts a function from a <b>String </b>to an <b>Int</b> into a function from an Option<String> to an Option<Int>. In this example we are lifting the <b>parseOct </b>function which parses a <b>String </b>to an <b>Int</b> with radix 8.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val liftLength: (Option<String>) -> Option<Int> = lift(String::length)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(3), liftLength(some("ken")))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(none(), liftLength(none()))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val parse: (Int) -> (String) -> Int = flip(C2(Integer::parseInt))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val parseOct: (String) -> Int = parse(8)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val liftParseOct: (Option<String>) -> Option<Int> = lift(parseOct)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(7), liftParseOct(some("7")))</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(83), liftParseOct(some("123")))</span></div></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">To map a binary function over two <b>Option</b> values we use the <b>fmap2</b> library function:</div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;"><br /></span></div><div style="text-align: justify;"><span style="font-family: arial; font-size: x-small;">fun <A, B, C> fmap2(oa: Option<A>, ob: Option<B>, f: (A) -> (B) -> C): Option<C></span></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">In the following we combine an Option<String> and an Option<Int> into an Option<Boolean> where the resulting <b>Boolean </b>is true if the <b>Int </b>and the <b>String </b>length are the same.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val opName: Option<String> = some("ken")</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val opInt3: Option<Int> = some(3)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">val opInt6: Option<Int> = some(6)</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(true), fmap2(opName, opInt3){str -> {n -> (str.length == n)}})</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(false), fmap2(opName, opInt6){str -> {n -> (str.length == n)}})</span></div></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Composing <b>Option </b>instances is just the beginning. We will need to compose an <b>Option </b>type with some other type. For example, we may wish to convert a List<Option<A>> into an Option<List<A>> where the values in the result <b>List </b>that is wrapped in an <b>Option </b>are those values from the source <b>List </b>that were wrapped in <b>Option</b>. Usually, we want a Some<List<A>> if all the elements in the <b>List </b>are a Some<A>, and a <b>None </b>if one or more elements in the <b>List </b>are a <b>None</b>. The library function <b>sequenceOption </b>from <b>ListF </b>does just this:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(some(ListF.of(1, 2, 3, 4)), ListF.of(some(1), some(2), some(3), some(4)).sequenceOption())</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(none(), ListF.of(some(1), some(2), none(), some(4)).sequenceOption())</span></div><div><span style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(none(), ListF.of(some(1), some(2), none(), none()).sequenceOption())</span></div></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><b style="font-family: arial;">Effectful computations</b></div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">Consider the class <b>Account </b>that might be used in a banking application. A function <b>open </b>will receive details of the account through its parameter list to create and initialize an <b>Account</b>. The return type of <b>open </b>is <b>Account </b>but how do we handle failure? We might choose to return null or throw an exception. However, we can better handle failure as <i>effects </i>that compose with other abstractions in our code. An effect adds capabilities to to a computation so that we do not have to use side effects. An effect is usually modeled as a type that wraps these additional capabilities around some type. Our Option<A> adds the capability of optionality to the type A. Hence the return type for the function <b>open </b>would be Option<Account>. We we see many more examples of this from our custom library.</div><div style="text-align: justify;"><br /></div></div><div style="text-align: justify;"><div><br /></div><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;"><br /></span></div></div>
Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-75131216792086926062020-05-06T06:13:00.008-07:002022-11-04T07:05:23.123-07:00Kotlin: Function type<span style="font-family: arial; font-size: large;"><b>Kotlin: Function type</b></span><br />
<br />
<div style="text-align: justify;">
<div class="MsoNormal">
<span style="font-family: inherit;"><i>In this blog we introduce the notion of function types. </i></span><i>A function type is syntactic sugar for a (function) interface which is not used directly. These function types have a special notation that corresponds to the signature of functions describing their parameter types and their return type.</i></div><div class="MsoNormal"><i style="font-family: inherit;"><br /></i></div><div class="MsoNormal"><i style="font-family: inherit;">In
this blog we also introduce higher
order functions: functions that are parameters to other functions and the
results of executing functions. <span style="background: white;">It turns out that </span>they are a highly expressive mechanism <span style="background: white;">for </span>defining
behaviors without recourse to more primitive programming constructs such as
for loops and if statements. <span style="background: white;">They are a really
powerful way of solving problems and thinking about programs.</span></i></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><i><span style="background: white;"><br /></span></i></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><i><span style="background: white;">This material is a precursor to a series of blogs on immutable and persistent data types in Kotlin. </span></i></span><i>The features described here are included in the custom library <b>Dogs </b>consisting of immutable and persistent data types as well as a mix of functional primitives.</i></div>
</div>
<br />
<br />
<div>
<br />
<span style="font-family: arial; font-size: medium;"><b>Functions</b></span><br />
<br />
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">Kotlin supports
<i>functions </i>at a number of levels. A function can be declared at <i>package level</i>.
We might develop an application in terms of these functions. This might be appropriate for a utility application that performs some simple processing of,
say, data stored in a file or spreadsheet. The data might be represented as,
say, data classes but the program architecture is procedural.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Functions can also be declared in
the body of other functions. Such <i>local functions</i> have a support role to the
enclosing function. These nested functions are inaccessible to other parts of
the code and so reduce the concepts surrounding the supported function.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit; text-indent: 36pt;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit; text-indent: 36pt;">Me</span><i style="font-family: inherit; text-indent: 36pt;">mber
functions </i><span style="font-family: inherit; text-indent: 36pt;">in a class define the behaviors of object instances of that class.
</span><i style="font-family: inherit; text-indent: 36pt;"><span style="color: #2a2a2a;">Extension functions</span></i><span style="color: #2a2a2a; font-family: inherit; text-indent: 36pt;"> in Kotlin enable you to add new
functions to existing classes without creating a new derived class,
recompiling, or otherwise modifying the original class. Extension functions are
a special kind of ‘static’ function, but they are called as if they were
instance functions on the extended type. For client code there is no apparent
difference between calling an extension function and the member functions that are
actually defined in a class.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
Below are a number of simple functions.</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #2a2a2a; font-family: inherit; text-indent: 36pt;"><br /></span></div>
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun increment(n: Int): Int = 1 + n // increment: (Int) -> Int<br />fun negate(n: Int): Int = -n // negate: (Int) -> Int<br />fun sum(m: Int, n: Int): Int = m + n // sum: (Int, Int) -> Int<br />fun same(text: String, len: Int): Boolean = // same: (String, Int) -> Boolean<br /> (text.length == len)<br /><br />assertEquals(-4, negate(increment(3)))<br />assertEquals(12, sum(3, sum(4, 5)))<br />assertEquals(true, same("four + nine", 13))</span><br />
<br />
<br />
<br />
<b><span style="font-family: arial; font-size: medium;">Function types</span></b><br />
<br />
<div class="MsoNormal" style="text-align: justify;">
<div class="MsoNormal">
<div class="MsoBodyText">
<span style="font-family: inherit;">In Kotlin
functions are <i>first class citizens</i>. The implication of this is that a
function can be treated like any other object. For example, a <b>String</b> object can be referenced in a
value binding, can be passed as the actual parameter in a function call, can be
the return value from a function call, can be a property of a class, can be
an element of a container such as a <b>List</b>,
and can be considered an object instance of the <b>String</b> class and call one of its member functions on it (such as
the <b>length</b> member function or the <b>indexOf</b> member function).</span><span style="font-family: "comic sans ms";"><o:p></o:p></span></div>
</div>
</div>
<div class="MsoNormal">
<br />
<div>
<div style="text-align: justify;">
<span style="font-family: inherit;">These
features of a <b>String</b> object are also
applicable to a function object. A
function can be referenced in a value binding, can be passed as the actual
parameter in a function call or be the return value from a function call
(giving rise to higher order functions), can be the property of a class, can be
an element of a container such as a <b>List</b>,
and can be considered an object instance of some function class and call one of
its member functions on it (such as the <b>invoke</b>
member function).</span></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Kotlin
is a statically typed programming language so we are required to provide the
type of each object either explicitly or by type inference. To use a function
we must have a way to present a <i>function
type</i>. A function type is syntactic sugar for a (function) interface which
is not used directly. The syntax of a function type is:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-left: 14.2pt; text-align: justify;">
<span><span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">(parameter type,
parameter type, …) -> return type</span><span style="font-family: inherit; font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">with
the left side specifying the function parameter types enclosed in parentheses,
and the right side specifying the return type of the function.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">These function types have a special notation that corresponds to the signature of functions describing their parameter types and their return type. In the following listing the <b>val</b> bindings for <b>inc</b>, <b>neg</b> and <b>add</b> include these function types.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun increment(n: Int): Int = 1 + n <span> </span>// increment: (Int) -> Int</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun negate(n: Int): Int = -n <span> </span><span> </span>// negate: (Int) -> Int</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun sum(m: Int, n: Int): Int = m + n <span> </span>// sum: (Int, Int) -> Int</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val inc: (Int) -> Int = ::increment</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val neg: (Int) -> Int = ::negate</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val add: (Int, Int) -> Int = ::sum</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(-4, negate(increment(3)))</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(12, sum(3, sum(4, 5)))</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(-4, neg(inc(3)))</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(12, add(3, add(4, 5)))</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(-4, neg.invoke(inc.invoke(3)))</span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(12, add.invoke(3, add.invoke(4, 5)))</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
To obtain an instance of a function type we use a <i>callable reference</i> to an existing function declaration with the expression ::<b>increment</b> which is the value of the function type (Int) -> Int.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
There are several other ways to obtain an instance of a function type. Two of the more common are <i>anonymous functions</i> and <i>lambda expressions</i>.<span style="font-family: inherit;"> An
anonymous function (or <i>function expression</i>) has a regular
function declaration except its name is omitted. The parameter types and return
type are specified as for regular functions. The body of an anonymous function
can be an expression or a block. <span style="background: white;">The return type of the anonymous function
can be inferred automatically from the function if it is an expression and has
to be specified explicitly for the anonymous function if it is a block. Here are some examples:</span></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><span style="background: white;"><br /></span></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val isOdd = fun(n: Int): Boolean = (n % 2 == 1)</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val isEven: (Int) -> Boolean = fun(n) = (n % 2 == 0)</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val add: (Int, Int) -> Int = fun(m: Int, n: Int): Int = (m + n)</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val sum: (Int, Int) -> Int = add</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(true, isOdd(5))</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(false, isEven(5))</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(7, add(3, 4))</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-size: x-small;"><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; font-family: arial;"></span></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(7, sum(3, 4))</span></div>
<div class="MsoNormal">
<br /></div><div class="MsoNormal" style="text-align: justify;">The val binding <b>isOdd </b>has the regular function declaration (with its name omitted). The val binding for <b>isEven </b>includes a function type so the types of the parameter and the return type can be omitted. The val binding for <b>add </b>redundantly includes both the function type and the function parameter and return type. Finally, the <b>sum </b>val binding includes the function type but this could be omitted as the Kotlin compiler will infer the correct type.</div><div class="MsoNormal"><br /></div>
<div class="MsoNormal">
<span style="background: white; font-family: "comic sans ms";"><o:p></o:p></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><span style="color: #333333;">Lambda expressions (or
<i>function literals</i>) are essentially anonymous functions that we can treat as
values –<b> </b></span><span style="background: white; color: #333333;">we can, for example,
pass them as arguments to functions, return them, or do any other thing we
could do with a normal object. A lambda expression is presented as a code
block:<o:p></o:p></span></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText" style="margin-left: 14.2pt;">
<span style="background: white; color: #333333;"><span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">{parameter: type, parameter: type, … -> code body}</span><span style="font-family: inherit; font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="background: white; color: #333333;"><span style="font-family: inherit;">where the type can be omitted if
it can be inferred. </span><o:p></o:p></span><span style="font-family: inherit;"><span style="background: white; color: #333333;">Like anonymous
functions, lambda expressions are instances </span>of some appropriate interface with an <b>invoke</b> member function. Then { ...
}.invoke(...) executes the function <b>invoke</b>
on the lambda expression { ... } and passing the actual parameters ( ... ). Here are some examples:</span></div>
<div class="MsoBodyText">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(9, {n: Int -> n * n}.invoke(3))</span></div>
<div class="MsoBodyText">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(9, {n: Int -> n * n}(3))<span> </span><span> // invoke is inferred</span></span></div>
<div class="MsoBodyText">
</div>
<div class="MsoBodyText">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(3, {n: Int -> n + 1}(2))<span> </span><span> // invoke is inferred</span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Since
a lambda expression is a Kotlin object, then we can bind an identifier to it.
The identifier is a reference to that function and the function can be called
through the identifier:</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val square = {n: Int -> n * n}</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val increment = {n: Int -> n + 1}</span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(9, square.invoke(3))</span></div>
<div class="MsoNormal">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(9, square(3))<span> </span><span> <span> </span></span></span><span>// invoke is inferred</span></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(3, increment(2))<span> </span></span><span>// invoke is inferred</span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: inherit;">The
full syntactic form for binding a lambda expression would be shown by the
following example:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 14.2pt;">
<span><span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">val sum: (Int, Int)
-> Int = {m: Int, n: Int -> m + n}</span><span style="font-family: inherit; font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">The
formal parameters are presented exactly as for a normal function: the name and
type for each parameter. The lambda expression is enclosed by matching braces
and the parameter list and function body is separated by <b>-></b>.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">More commonly we will associate the
function type with the bound reference. The parameter types and the return
type represent the function type and would look like:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 14.2pt;">
<span><span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">val sum: (Int, Int)
-> Int = {m, n -> m + n}</span><span style="font-family: inherit; font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: inherit;">Here,
<b>sum</b> is bound to a function that
expects two <b>Int</b>s and returns an <b>Int</b>.<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Simple as these function type
signatures may appear, they are the key to unlocking some of the more advanced
programming we shall encounter with functions. The higher-order extension
functions for the custom <b>List</b>
class are examples of the more powerful capabilities possible with lambda
expressions.</span><span style="font-family: "comic sans ms";"><o:p></o:p></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The arrow notation in function types is <i>right associative</i>. The function type (String) -> (Int) -> Boolean describes a function that accepts a single <b>String </b>parameter and returns a function with the type (Int) -> Boolean. Since parentheses can be used in function types the latter is equivalent to (String) -> ((Int) -> Boolean). Notice that the function type ((String) -> Int) -> Boolean describes a function that returns a <b>Boolean </b>and take a single function parameter of the type (String) -> Int.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: arial; font-size: medium;"><b>Higher order functions</b></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">A function can
be passed as a parameter to another function. A function can be the return value
from the call to a function. Such functions are called <i>higher order
functions</i>. Through functions as parameters and functions as results we are
able to fully exploit the machinery of functions, such as function composition.
The resulting function declarations can be both more concise and more readable
than traditional approaches.</span><br />
<span style="font-family: inherit; text-indent: 36pt;"><br /></span>
<span style="font-family: inherit; text-indent: 36pt;">In
the following listing function </span><b style="font-family: inherit; text-indent: 36pt;">doTwice</b><span style="font-family: inherit; text-indent: 36pt;"> is a </span><span style="font-family: inherit; text-indent: 36pt;">higher
order function</span><span style="font-family: inherit; text-indent: 36pt;"> as it expects a function as its second parameter. The
interpretation of the signature for </span><b style="font-family: inherit; text-indent: 36pt;">doTwice</b><span style="font-family: inherit; text-indent: 36pt;">
is that it returns an </span><b style="font-family: inherit; text-indent: 36pt;">Int</b><span style="font-family: inherit; text-indent: 36pt;"> as its
value. Two parameters are required, the first of which is an </span><b style="font-family: inherit; text-indent: 36pt;">Int</b><span style="font-family: inherit; text-indent: 36pt;">. The second parameter is the </span><i style="font-family: inherit; text-indent: 36pt;">function
parameter</i><span style="font-family: inherit; text-indent: 36pt;">. The effect of </span><b style="font-family: inherit; text-indent: 36pt;">doTwice</b><span style="font-family: inherit; text-indent: 36pt;">
is to apply the function twice to the numeric parameter.</span></div>
<br />
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun triple(n: Int): Int = 3 * n // as function</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val quadruple: (Int) -> Int = {n -> 4 * n} // as lambda expression</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val twelveTimes = fun(n: Int): Int = triple(quadruple(n)) // anonymous function</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun doTwice(n: Int, f: (Int) -> Int): Int = f(f(n))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(6, triple(2))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(12, quadruple(3))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(36, twelveTimes(3))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(18, doTwice(2, ::triple))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(48, doTwice(3, quadruple))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(144, doTwice(1, twelveTimes))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(75, doTwice(3, {n -> 5 * n}))</span></div>
<div style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(75, doTwice(3){n -> 5 * n})</span></div>
<div><br /></div>
<div style="text-align: justify;">
<span style="font-family: inherit;"><span style="font-family: inherit;">Consider
a function with two parameters of
type <b>String</b> and <b>Int</b> returning a <b>Boolean</b>
result. If we are required to </span><span style="font-family: inherit;">partially
apply the function (see below) on the <b>Int</b> parameter then we require the <b>Int</b> to be the first parameter. </span><span style="font-family: inherit;">We define a
function that takes a binary function as parameter, and which returns a binary
function that accepts its parameters in the opposite order. The <b>flip</b> function is declared as:</span></span></div>
<div class="MsoBodyText"><br /></div>
<div class="MsoBodyText" style="margin-left: 14.2pt;">
<span><span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">fun <A, B, C> flip(f: (A, B) -> C):
(B, A) -> C =<o:p></o:p></span></span></div>
<div class="MsoBodyText" style="margin-left: 14.2pt;">
<span><span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;"> {b:
B, a: A -> f(a, b)}</span><span style="font-family: inherit; font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoBodyText">
<br /></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;">We use a lambda
expression for the result. The function is defined generically so it can be
applied to all parameter types. Function <b>flip</b>
is a generic higher order function taking a function parameter and delivering a
function result.</span><span style="font-family: "comic sans ms";"><o:p></o:p></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun isSameSize(str: String, n: Int): Boolean = (str.length == n)</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val isSame: (Int, String) -> Boolean = flip(::isSameSize)</span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertTrue(isSame(3, "Ken"))</span></div>
<div class="MsoBodyText" style="text-align: justify;">
</div>
<div class="MsoBodyText" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertFalse(isSame(3, "John"))</span></div>
<div class="MsoBodyText" style="text-align: justify;"><br /></div>
<div style="text-align: justify;">
<span><span style="font-family: inherit;">The
function </span><b style="font-family: inherit;">flip</b><span style="font-family: inherit;"> is provided by the <b>Dogs </b>custom library. It is defined in the object declaration </span><b style="font-family: inherit;">FunctionF</b><span><span style="font-family: inherit;"> from the </span><span style="font-family: times;"><span style="background-color: white; color: #080808;">com.adt.kotlin.dogs.fp</span> </span><span style="font-family: inherit;">package. It is overloaded to operate on both an uncurried binary function and a curried binary function (see later).</span></span></span></div>
<span style="font-family: inherit;">
</span>
<br />
<br />
<br />
<br />
<span style="font-family: arial; font-size: medium;"><b>Function composition</b></span></div>
<div>
<br /></div>
<div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Perhaps one of the more important
characteristics of functions is <i>composition</i>, wherein you can define one
function whose purpose is to combine other functions. Using composition, two or
more simple functions can be combined to produce a more elaborate one. <span lang="EN">For example,
suppose we have two arithmetic functions <span class="texhtml"><i>f</i></span>
and <span class="texhtml"><i>g</i></span>. One way of composing these two
functions would be to first compute <span class="texhtml"><i>y</i></span>, and
then to compute <span class="texhtml"><i>z</i></span> from <span class="texhtml"><i>y</i></span>,
as in <span class="texhtml"><i>y</i> = <i>g</i>(<i>x</i>)</span> followed by <span class="texhtml"><i>z</i> = <i>f</i>(<i>y</i>)</span>. One could get the same
result with the single composition written <i>z
= <span class="texhtml">f(g(x))</span></i>. We write this as f ● g, meaning function f
composed with function g (sometimes also described as f after g).<o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;">Function
composition lets us compose a solution by combining separately designed and
implemented functions. Structuring a large solution into separate functions
simplifies the programming activity. The functions can be defined, implemented
and tested separately. Simple functions can be used to construct more elaborate
functions, reducing the burden and complexity of a system. The functions can
also be defined for one application and re-used in other applications.</span><span style="font-family: "comic sans ms";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun f(n: Int): Int = 2 * n + 3</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun g(n: Int): Int = n * n</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val gf: (Int) -> Int = compose(::g, ::f)</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val fg1: (Int) -> Int = ::f compose ::g</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val fg2: (Int) -> Int = ::f o ::g</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(121, gf(4))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(35, fg1(4))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-size: x-small;"><span lang="EN" style="font-family: arial;"></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(35, fg2(4))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Pay attention to the signature of <b>compose</b>.
It is a function that takes two functions as its parameters and returns a
function as its result. The second function <b>g</b> accepts an input of the type A and delivers a result of type B.
The result is passed as input to the first function <b>f</b> and delivers a result of type C. Hence the composed function has
the signature (A) -> C:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C = {a: A -> f(g(a))}</span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">The function </span><b>compose</b><span style="font-family: inherit;"> is provided by the <b>Dogs </b>library. </span><span style="font-family: inherit;">Note the complementary infix functions </span><b style="font-family: inherit;">compose</b><span style="font-family: inherit;"> and </span><b style="font-family: inherit;">o</b><span style="font-family: inherit;">.
Both are defined as an inf</span><i style="font-family: inherit;">ix function </i><span style="font-family: inherit;">on
the interface that represents the function type (B) -> C. They expects a
function parameter with type (A) -> B and composes them using </span><b style="font-family: inherit;">compose</b><span style="font-family: inherit;"> to deliver the function (A)
-> C.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">In the following example function <b>compose</b> is used to compose <b>isEven</b> and <b>strLength</b>. In some circumstances the Kotlin compiler is unable to infer the actual types for the type parameters A, B and C. In that case you must assist the compiler and provide the actual type parameters. This is shown in the call to <b>compose</b>, though in this case it is unnecessary since the compiler correctly infers these types.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun strLength(str: String): Int = str.length</span><br />
<span face=""arial" , "helvetica" , sans-serif">fun isEven(n: Int): Boolean = (n % 2 == 0)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val strIsEven: (String) -> Boolean = compose(::isEven, ::strLength)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(false, strIsEven("Ken"))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(true, strIsEven("John"))</span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;">The order in f compose g is significant and can be confusing: f compose g means apply g and then apply f to the result. The <b>Dogs </b>library also declares the <b>forwardCompose</b> function which takes its parameters in the opposite order to <b>compose</b>:</span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">fun <A, B, C> forwardCompose(f: (A) -> B, g: (B) -> C): (A) -> C = {a: A -> g(f(a))}</span></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN">The library also declares the infix forms <b>forwardCompose</b>, <b>fc</b> and <b>pipe</b>:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val successor: (Int) -> Int = {n -> 1 + n} // as function literal</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun triple(n: Int): Int = 3 * n // as function</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val quadruple = fun(n: Int): Int = 4 * n // as function expression</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val twelveTimes: (Int) -> Int = compose(::triple, quadruple)</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val threePlusOne: (Int) -> Int = ::triple fc successor</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(60, twelveTimes(5))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(16, threePlusOne(5))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val up2: (Int) -> Int = successor o successor</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val upDown: (Int) -> Int = successor o {n -> n - 1}</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val up2Down2: (Int) -> Int = up2 pipe {n -> n - 2}</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(5, up2(3))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(5, upDown(5))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-size: x-small;"><span lang="EN" style="font-family: arial;"></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(5, up2Down2(5))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;">The function type signatures are an
important resource in this work. They alert us when compositions would not
work. For example, consider that we have the function f: (Int) -> Boolean
and the function g: (String) -> Int. The signature for <b>compose</b> tells us compose(f, g) will produce a function with the
signature (String) -> Boolean. Equally, the signature reveals that
compose(g, f) will not compose correctly.<o:p></o:p></span></span><br />
<span lang="EN"><span style="font-family: inherit;"><br /></span></span>
<span lang="EN"><span style="font-family: inherit;">It is relatively easy to prove that map(</span></span>f ● g, xs) = (map f ● map g)(xs) for a <b>List </b>xs. Applying f ● g to every element of a list is the same as applying <b>g </b>to every member of the list and then applying <b>f </b>to every member of the resulting list. The equality demonstrates how we might refactor our code to make it more efficient. If our code includes (map f ● map g) then we optimize it with map(f ● g). The former makes one pass across the initial list and then a second pass across the result list. The latter makes only a single pass across the initial list reducing the amount of work to be done.<br />
<span lang="EN"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val f: (Int) -> Int = {n -> 2 * n}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val g: (Int) -> Int = {n -> n + 1}</span><br />
<span face=""arial" , "helvetica" , sans-serif">val map: ((Int) -> Int) -> (List<Int>) -> List<Int> = {f -> {list -> list.map(f)}}</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val fg: (Int) -> Int = f compose g</span><br />
<span face=""arial" , "helvetica" , sans-serif">val mapfmapg: (List<Int>) -> List<Int> = map(f) compose map(g)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val numbers: List<Int> = ListF.of(1, 2, 3, 4)</span><br />
<span lang="EN"><span face=""arial" , "helvetica" , sans-serif"></span></span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals(map(fg)(numbers), mapfmapg(numbers))</span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;">Perhaps
rather pedantically the full signature for function literals will be given.
Kotlin's type inferencing engine would make some parts of the signature
unnecessary. Their inclusion is for the benefit of the reader. Their absence may make some of the code opaque to the reader and so the full signatures are
retained.</span><span style="font-family: "comic sans ms";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: arial; font-size: medium;"><b>Curried functions</b></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;"><br /></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">In
this section we demonstrate how a single function can effectively define a
complete family of functions. Having defined the parent function, we are able
to specialize from it a number of related functions. To achieve this we use the
notion of <i>currying</i>, named after the
mathematician Haskell Curry.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="background-color: white; font-family: inherit; text-indent: 36pt;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="background-color: white; font-family: inherit; text-indent: 36pt;">Currying is the process of transforming a function that takes
multiple parameters into a function that takes just a single parameter and
returns another function which accepts further parameters.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Consider the <span lang="EN">function </span><b>add</b>
which adds together two <b>Int</b>
parameters. Its definition is given by:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-left: 14.2pt; text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">fun add(m: Int, n:
Int): Int = m + n</span><span style="font-family: inherit; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">The
type signature informs us that <b>add</b> is a function which when given a pair of <b>Int</b>s
will return an <b>Int</b>. If we were
able to call function <b>add</b> and give only one actual parameter, then
we would get a result which is itself another function. For example, if we
could call <b>add</b> with the parameter 1, then effectively the
first formal parameter <b>m</b> is replaced throughout the definition for <b>add</b>
with this value. Further, since the value for the parameter <b>m</b>
is now specified, then this formal parameter can be removed from the
definition. We then effectively produce the function:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-left: 14.2pt; text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">fun add1(n: Int): Int =
1 + n</span><span style="font-family: inherit; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN"><span style="font-family: inherit;">
</span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">one that takes a single numeric parameter and
returns its successor to that value.</span><span style="font-family: "comic sans ms";"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">In
the following listing we declare the <b>add</b>
function in the usual way and use it in the first assert. Since a function can
be the result for a function, then any multi-parameter function can be
converted into a series of one parameter functions. The function <b>sum</b> is defined to operate like <b>add</b> but
in its curried form. We execute <b>sum </b>with the call sum(6)(7). Observe how <b>sum10</b> is defined by calling <b>sum</b> with its first parameter delivering a function that adds 10 to its parameter.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun add(m: Int, n: Int): Int = m + n</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val sum: (Int) -> (Int) -> Int = {m: Int -> {n: Int -> m + n}}</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val sum10: (Int) -> Int = sum(10)</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(7, add(3, 4))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(13, sum(6)(7))</span></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(17, sum10(7))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Suppose
we want to develop a curried version of a binary function <b>f</b> which is <i>uncurried</i> and
of the type (A, B) -> C. This binary function <b>f</b> expects its parameters as a pair but its curried version will
apply them sequentially. We therefore have to form them into a pair before
applying <b>f</b> to them. The custom function <b>C2</b> does exactly this:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-left: 14.2pt; text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="font-family: arial; font-size: x-small;">fun <A, B, C> C2(f:
(A, B) -> C): (A) -> (B) -> C = {a: A -> {b: B -> f(a, b)}}</span><span style="font-family: inherit;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">Again,
the signature reveals what is happening. Function <b>C2</b> expects a function as its parameter. That parameter function has
the signature (A, B) -> C, an uncurried binary function. Function <b>C2</b> returns the curried variant with the
signature (A) -> (B) -> C, as required. We can use <b>C2</b> where we need to transform an uncurried binary function into its
curried form:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun add(m: Int, n: Int): Int = m + n</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val sum: (Int) -> (Int) -> Int = C2(::add)</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(7, add(3, 4))</span></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(13, sum(6)(7))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div><div class="MsoNormal" style="text-align: justify;">The Dogs library define this function <b>C2 </b>as well as the related functions <b>C3</b>, <b>C4</b>, <b>C5</b> and <b>C6</b>. The library also includes the complementary functions <b>U2</b>, <b>U3</b>, <b>U4</b>, <b>U5</b> and <b>U6 </b>to uncurry curried functions.</div><div class="MsoNormal" style="text-align: justify;"><br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: arial; font-size: medium;"><b>Partial function application</b></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: inherit;">A key value of curried functions is that they can be <i>partially applied</i>. For example consider
the curried binary function <b>sum</b>
declared in the earlier example. In the listing the binding <b>sum10</b> is a function from <b>Int</b> to <b>Int</b> obtained by partially applying the
function <b>sum</b>. In effect the function
<b>sum10</b> is defined as:</span></div><div class="MsoNormal" style="text-align: justify;"><span style="font-size: small;"><br /></span></div><div class="MsoNormal" style="text-align: justify;"><span> <span style="font-family: arial; font-size: x-small;">val sum10: (Int) ->
Int = {n: Int -> 10 + n}</span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div><div class="MsoNormal" style="text-align: justify;">The <b>Dogs </b>library includes a number of variants of the function <b>partial</b>. Here, we are using:</div><div class="MsoNormal" style="text-align: justify;"><br /></div><div class="MsoNormal" style="text-align: justify;"><div class="MsoNormal"><span style="font-family: arial; font-size: x-small;">fun <A, B, C> partial(a: A, f: (A) -> (B) -> C): (B) -> C =</span></div><div class="MsoNormal"><span style="font-family: arial; font-size: x-small;"> {b: B -> f(a)(b)}</span></div></div><div class="MsoNormal" style="text-align: justify;"><br /></div><div class="MsoNormal" style="text-align: justify;">in the following code:</div><div class="MsoNormal" style="text-align: justify;"><br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">fun add(m: Int, n: Int): Int = m + n</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val sum: (Int) -> (Int) -> Int = {m: Int -> {n: Int -> m + n}}</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val sum1: (Int) -> Int = partial(1, sum)</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">val add10: (Int) -> Int = partial(10, ::add)</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(11, sum1(10))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span face=""arial" , "helvetica" , sans-serif" style="background-color: #cccccc; font-family: arial; font-size: x-small;">assertEquals(12, add10(2))</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: arial; font-size: medium;"><b>Further callable references</b></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
A callable reference to an existing function declaration was introduced earlier. A callable reference to a class member function or to a an extension function is also supported. In the following listing the first three <b>val </b>bindings refer to function members of the <b>String </b>class. In the callable reference String::length the function <b>length </b>of class <b>String </b>has no parameters and returns an <b>Int</b>. The function type for this includes the class <b>String</b> as the first function type parameter.<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">val strLength: (String) -> Int = String::length</span><br />
<span face=""arial" , "helvetica" , sans-serif">val subStr: (String, IntRange) -> String = String::substring</span><br />
<span face=""arial" , "helvetica" , sans-serif">val subStrC: (String) -> (IntRange) -> String = C2(String::substring)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val crop: (String) -> String = String::trim</span><br />
<span face=""arial" , "helvetica" , sans-serif">val clip: (String, (Char) -> Boolean) -> String = String::trim</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">val take: (Int) -> (String) -> String = flip(C2(String::take))</span><br />
<span face=""arial" , "helvetica" , sans-serif">val take4: (String) -> String = take(4)</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals(3, strLength("Ken"))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals("nn", subStr("Kenneth", 2..3))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals("nn", subStrC("Kenneth")(2..3))</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals("ken", crop(" ken "))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals("ken", clip("123ken4", Character::isDigit))</span><br />
<span face=""arial" , "helvetica" , sans-serif"><br /></span>
<span face=""arial" , "helvetica" , sans-serif">assertEquals("Kenn", take4("Kenneth"))</span><br />
<span face=""arial" , "helvetica" , sans-serif">assertEquals("Barc", take4("Barclay"))</span></span><br />
<br />
The callable reference operator :: can also <span style="font-family: inherit;"><span style="background-color: white; color: #333333;">be used with overloaded functions when the expected type is known from the context. This is shown using the overloaded <b>substring </b>function from class <b>String</b>.</span></span><br />
<span style="font-family: inherit;"><span style="background-color: white; color: #333333;"><br /></span></span>
<span style="font-family: inherit;"><span style="background-color: white; color: #333333;">At the time of writing (April 2020) there are some problems when using callable references to function members of a generic class. Workarounds are possible and need to be used.</span></span><br />
<br />
<br />
<br />
<span style="font-family: arial; font-size: medium;"><b>Case Study</b></span><br />
<br />
<span style="font-family: inherit;">This example includes a number of individual functions which together compile the index
of the words in a text document. The index is an alphabetical list of the words
and, for each word, the line numbers in the document on which it appears. The
solution is a composition of the functions that perform the various operations
on the text.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">We start by introducing a number of aliases that make it easier to interpret the signatures of the various functions:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">typealias Document = String</span><br />
<span face=""arial" , "helvetica" , sans-serif">typealias Line = String</span><br />
<span face=""arial" , "helvetica" , sans-serif">typealias Word = String</span><br />
<span face=""arial" , "helvetica" , sans-serif">typealias Number = Int</span><br />
<span face=""arial" , "helvetica" , sans-serif">typealias LineNumber = Pair<Line, Number></span><br />
<span face=""arial" , "helvetica" , sans-serif">typealias WordNumber = Pair<Word, Number></span><br />
<span face=""arial" , "helvetica" , sans-serif">typealias WordNumbers = Pair<Word, List<Number>></span></span><br />
<br />
The use of <b>Document</b>, <b>Line</b> and <b>Word</b>, for example, help to distinguish how a <b>String</b> is being used.<br />
<br />
We start with a <b>Document</b> and break it into one or more <b>Line</b> at the line breaks. The function to do this is called <b>lines</b> and has the signature:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">fun lines(document: Document): List<Line></span></span><br />
<br />
Once we have the lines from the document we use the function <b>numberedLines</b> to convert each <b>Line</b> to a <b>LineNumber</b>, pairing the line with its line number:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">fun numberedLines(lines: List<Line>): List<LineNumber></span></span><br />
<br />
At this point we have the means to convert a document into its lines and their corresponding line number:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;"> ::lines pipe ::numberedLines</span></span><br />
<br />
The next task is to break the numbered lines into words numbered with their line number:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">fun numberedWords(lines: List<LineNumber>): List<WordNumber></span></span><br />
<br />
This function additionally transforms each word to lowercase so that, for example, all the 'anonymous' and 'Anonymous' are considered identical. To group the word number pairs we sort them:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">fun sort(numberedWords: List<WordNumber>): List<WordNumber></span></span><br />
<br />
then merge the line numbers of adjacent matching words:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">fun merge(words: List<WordNumber>): List<WordNumbers></span></span><br />
<br />
Finally we provide the means whereby we select the first <b>n</b> elements:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <span style="font-family: arial;">val take: (Int) -> (List<WordNumbers>) -> List<WordNumbers></span></span><br />
<br />
Now we can define:<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">fun wordConcordance(n: Int): (Document) -> List<WordNumbers> =</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ::lines pipe ::numberedLines pipe ::numberedWords pipe ::sort pipe ::merge pipe take(n)</span></span><br />
<br />
The declaration of <b>wordConcordance</b> is a pipeline of six component functions glued through functional composition.<br />
<br />
We run our code against the following document:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">There are several other ways to obtain an instance of a function type</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">Two of the more common are anonymous functions and lambda expressions</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">An anonymous function or function expression has a regular function</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">declaration except its name is omitted The parameter types and return</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">type are specified as for regular functions The body of an anonymous</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">function can be an expression or a block The return type of the anonymous</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">function can be inferred automatically from the function if it is an expression</span><br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;">and has to be specified explicitly for the anonymous function if it is a block</span><br />
<br />
Executing concordance(7)(document) and printing the result delivers:<br />
<br />
<span face=""arial" , "helvetica" , sans-serif" style="font-size: x-small;"> <[(a, <[1, 3, 6, 8]>), (an, <[1, 3, 5, 6, 7]>), (and, <[2, 4, 8]>), (anonymous, <[2, 3, 5, 6, 8]>), (are, <[1, 2, 5]>), ... ]></span></div>
<div class="MsoNormal">
<br />
showing the word 'anonymous' appearing on lines 2, 3, 5, 6 and 8.<br />
<br />
If we run concordance(4)(document) we have the following correct assertion:<br />
<br />
<span style="background-color: #cccccc; font-family: arial; font-size: x-small;"><span face=""arial" , "helvetica" , sans-serif">assertEquals(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ListF.of(</span><br />
<span face=""arial" , "helvetica" , sans-serif"> WordNumbers("a", ListF.of(1, 3, 6, 8)),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> WordNumbers("an", ListF.of(1, 3, 5, 6, 7)),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> WordNumbers("and", ListF.of(2, 4, 8)),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> WordNumbers("anonymous", ListF.of(2, 3, 5, 6, 8))</span><br />
<span face=""arial" , "helvetica" , sans-serif"> ),</span><br />
<span face=""arial" , "helvetica" , sans-serif"> concordance</span><br />
<span face=""arial" , "helvetica" , sans-serif">)</span></span><br />
<div><br /></div><div style="text-align: justify;">Here, our aim was to build a concordance of the words in a document, namely, a pairing of each word and the line numbers on which it appears. The <b>Dogs </b>library includes the <b>MultiMap</b> data type - a <b>MultiMap </b>is a special kind of <b>Map</b>: one that allows a collection of elements to be associated with each key. Using a <b>MultiMap </b>would have simplified this solution.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;">This simple idea scales to the more realistic business problem of an order taking system for a manufacturing company. The workflow for the order taking system can be broken into smaller and simpler stages: validation, pricing, etc. We can create a pipeline to represent the business process as:</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><span style="font-family: arial; font-size: x-small;">class UnvalidatedOrder</span></div><div><span style="font-family: arial; font-size: x-small;">class ValidatedOrder</span></div><div><span style="font-family: arial; font-size: x-small;">class PricedOrder</span></div><div><span style="font-family: arial; font-size: x-small;">class CompletedOrder</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">fun validateOrder(uvo: UnvalidatedOrder): ValidatedOrder = TODO()</span></div><div><span style="font-family: arial; font-size: x-small;">fun priceOrder(vo: ValidatedOrder): PricedOrder = TODO()</span></div><div><span style="font-family: arial; font-size: x-small;">fun completeOrder(po: PricedOrder): CompletedOrder = TODO()</span></div><div><span style="font-family: arial; font-size: x-small;"><br /></span></div><div><span style="font-family: arial; font-size: x-small;">val placeOrder: (UnvalidatedOrder) -> CompletedOrder = ::validateOrder pipe ::priceOrder pipe ::completeOrder</span></div></div><div><br /></div><div style="text-align: justify;">Of course, any of the stages might give rise to some sort of failure. For example, when validating an order we might find the unvalidated order may have omitted the quantity for an order item or referenced an unknown item and we will have to consider how to address failure.</div><div style="text-align: justify;"><br /></div><div style="text-align: justify;"><div><br /></div><div><br /></div><div>The code for the Dogs library can be found at:</div><div><div><br /></div><span style="color: black;">https://github.com/KenBarclay/TBA</span></div><div><span style="color: black;"><br /></span></div></div></div></div>
</div>
</div>
Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-32260617499788064902014-04-08T04:31:00.000-07:002014-04-08T04:31:52.647-07:00Kotlin: Pattern matchingThe past year I have evolved a simple <i>pattern matching</i> scheme that I now automatically incorporate into new Kotlin class hierarchies. The scheme is trivial to include, costs nothing to program and offers some beneficial features. Its development is thanks to the many nice features offered by Kotlin.<br />
<br />
Consider the development of an immutable list type. The architecture comprises the trait <b>ListIF</b>, the abstract class <b>ListAB</b>, and the two concrete classes <b>Nil </b>and <b>Cons</b>. The <b>ListIF </b>trait operates as an interface, introducing the behaviours supported. The abstract class <b>ListAB </b>is the home for the implementation of most of the common behaviours. The concrete classes <b>Nil </b>and <b>Cons </b>are used to create list instances.<br />
<br />
The implementation for this architecture is shown in Example 1. Note the <b>match </b>member function introduced in the trait. This is the pattern matching scheme for this class hierarchy. The function is given two parameters, one for each concrete class. The first parameter is a function to convert a <b>Nil </b>into the result type <b>B</b>. The second parameter is a function from a <b>Cons </b>to the result type <b>B</b>.<br />
<br />
The concrete subclasses <b>Nil </b>and <b>Cons </b>override the definition for <b>match</b>. In the class <b>Nil </b>the first parameter is invoked against the <b>Nil </b>instance. In the class <b>Cons </b>the second parameter is invoked against the <b>Cons </b>instance. This pattern matching scheme is effectively the <i>strategy design pattern</i>.<br />
<br />
<b>Example 1</b>: <i>Pattern matching</i><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example1</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import kotlin.test.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">trait ListIF<A> {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fun size(): Int</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fun length(): Int</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fun interleave(xs: ListIF<A>): ListIF<A></span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fun <B> match(nil: (Nil<A>) -> B, cons: (Cons<A>) -> B): B</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">abstract class ListAB<A> : ListIF<A> {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> override fun size(): Int {...}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> override fun length(): Int {...}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> </span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> override fun interleave(xs: ListIF<A>): ListIF<A> {...}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">class Nil<A> : ListAB<A>() {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> override fun <B> match(nil: (Nil<A>) -> B, cons: (Cons<A>) -> B): B = nil(this)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">class Cons<A>(val hd: A, val tl: ListIF<A>) : ListAB<A>() {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> override fun <B> match(nil: (Nil<A>) -> B, cons: (Cons<A>) -> B): B = cons(this)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val xs: ListIF<Int> = Cons(1, Cons(3, Cons(5, Nil<Int>())))</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val ys: ListIF<Int> = Cons(2, Cons(4, Nil<Int>()))</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(3, xs.size())</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(2, ys.length())</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(4, xs.interleave(ys).length())</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<div>
<br /></div>
<div>
The definition for member function <b>size </b>is:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">override fun size(): Int {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return this.match(</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(nil: Nil<A>) -> 0},</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(cons: Cons<A>) -> 1 + cons.tl.size()}</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span></div>
</div>
<div>
<br /></div>
<div>
A match is performed against the recipient list and if it is empty then zero is returned. If the list is non empty then we return 1 plus the size of the remaining list. Of course we could achieve the same using a <b>when </b>clause and a number of <b>is </b>selector clauses. However, it is incumbent on the programmer to provide all the necessary choices. With the <b>match </b>function if you omit a choice you get a compiler error.</div>
<div>
<br /></div>
<div>
The second function literal given to <b>match </b>reveals another feature. The formal parameter <b>cons </b>is of type <b>Cons </b>and is effectively a <i>smart cast</i> of <b>this</b>. Hence in the body of this function literal we can reference the <b>tl </b>property of <b>cons</b>.</div>
<div>
<br /></div>
<div>
The definition for member function <b>interleave </b>shows how we handle nested pattern matching:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">override fun interleave(xs: ListIF<A>): ListIF<A> {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return this.match(</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(nil1: Nil<A>) -> Nil<A>()},</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(cons1: Cons<A>) -></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> xs.match(</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(nil2: Nil<A>) -> Nil<A>()},</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(cons2: Cons<A>) -> Cons(cons1.hd, Cons(cons2.hd, cons1.tl.interleave(cons2.tl)))}</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span></div>
</div>
<div>
<br /></div>
<div>
Interleaving the values from two lists requires a number of considerations. They are fully captured by the nested pattern matching. If the first list (<b>this</b>) is empty then an empty list is delivered. If the first list is not empty then we look to the second list (<b>xs</b>). If this is empty then an empty list is returned. Otherwise, for two non empty lists we prefix the head of the first and the head of the second on to interleaving their tails. As well as a type safe implementation of our logic it also allows us to reason about its correctness before we test it.</div>
<div>
<br /></div>
<div>
The recursive definition of the list data type naturally leads to a recursive definition of the classes and its member functions. Here is member function <b>length</b>:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">override fun length(): Int {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fun recLength(xs: ListIF<A>, acc: Int): Int {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return xs.match(</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(nil: Nil<A>) -> acc},</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> {(cons: Cons<A>) -> recLength(cons.tl, 1 + acc)}</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return recLength(this, 0)</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span></div>
</div>
<div>
<br /></div>
<div>
The nested function <b>recLength </b>has an accumulating parameter so that the recursive call might exploit tail call optimization. If I understand the Kotlin annotation <b>tailRecursive </b>this does not apply here since the recursive call is nested in the function literal. Perhaps the clever people at IntelliJ could find a way so that I can have my cake and eat it.</div>
<div>
<br /></div>
<div>
Of course not all my class hierarchies are defined recursively and so this issue does not arise. The pattern matching scheme is inexpensive to implement, is type safe, supports smart casts and a clarity in function bodies that we can reason about their correctness.</div>
<div>
<br /></div>
Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-57268092155972364332014-02-14T07:16:00.000-08:002014-02-14T07:16:07.607-08:00Kotlin: An Option type #2<span style="font-family: inherit;">The first blog introduced the <b>OptionIF<T></b> trait and some of the supporting member functions. The package level functions <b>inject </b>and <b>bind </b>are used to make the <b>OptionIF<T></b> trait into a <i style="font-weight: normal;">monad</i>. A
monad is a way to structure computations in terms of values and sequences of
computations using those values. Monads allow the programmer to build up
computations using sequential building blocks, which can themselves be
sequences of computations. The monad determines how combined computations form
a new computation and frees the programmer from having to code the combination
manually each time it is required. It is useful to think of a monad as a
strategy for combining computations into more complex computations. The <b>inject </b>and <b>bind </b>functions have the signatures:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun <T> inject(t: T): OptionIF<T></span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun <T, V> bind(op: OptionIF<T>, f: (T) -> OptionIF<V>): OptionIF<V></span><br />
<span style="font-family: inherit;"><br /></span>
The <b>inject </b>function is simply a factory method to create an instance of <b>OptionIF<T></b>.<br />
<br />
<div class="MsoBodyText">
<span style="font-family: inherit;">The basic
intuition behind the <b>bind</b> operation
is that it allows us to combine two computations into one more complex
computation and allows them to interact with one another. The first parameter
type <b>OptionIF<T></b> represents the first computation. Significantly, the second parameter
type is T -> OptionIF<V> which can, given the result of the first computation,
produce a second computation to run. In other words bind(op){t -> ... } is a
computation which runs <b>op </b>and binds
the value wrapped in <b>op </b>to the
function literal parameter <b>t</b>. The function
body then decides what computation to run using the value for <b>t</b>.</span><span style="font-family: Comic Sans MS;"><o:p></o:p></span></div>
<div class="MsoBodyText">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText">
<span style="font-family: inherit;">Example 5 demonstrated the <b>map </b>member function of <b>OptionIF<T></b>. Example 6 shows how we might achieve the same using <b>inject </b>and <b>bind</b>. The <b>mapped </b>function applies the function parameter <b>f </b>to the content of the option type parameter <b>op</b>. Significantly the definition of <b>mapped </b>does not have to distinguish between the concrete <b>OptionIF<A></b> types of <b>op</b>.</span></div>
<div class="MsoBodyText">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText">
<span style="font-family: inherit;"><b>Example 6</b>: <i>The monadic option type</i></span></div>
<div class="MsoBodyText">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example6</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import kotlin.test.*</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun <A, B> mapped(f: (A) -> B, op: OptionIF<A>): OptionIF<B> = bind(op){(a: A) -> inject(f(a))}</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val name: OptionIF<String> = Some("Ken Barclay")</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val absentName: OptionIF<String> = None<String>()</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(Some(11), mapped({(str: String) -> str.length()}, name))</span></div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(None<Int>(), mapped({str -> str.length()}, absentName))</span></div>
<div class="MsoBodyText">
</div>
<div class="MsoBodyText">
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span></div>
<div>
<br /></div>
<span style="font-family: inherit;">Example 7 demonstrates how we might use the monadic option type. Running the program with
the inputs 18, 27 and 9 delivers the result Some(Pair(2, 3)), demonstrating
that 18 and 27 are exactly divisible by 9. The inputs 18, 27 and 6 produce the
result<b> None</b>, showing that 18 and 27
and not both exactly divisible by 6.</span><br />
<div>
<br /></div>
<div>
<b>Example 7</b>: <i>Staircasing</i></div>
<div>
<br /></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example7</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />import kotlin.test.*<br />import com.adt.kotlin.data.immutable.option.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />fun divide(num: Int, den: Int): OptionIF<Int> {<br /> return if (num % den != 0) None<Int>() else Some(num / den)<br />}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />fun division(a: Int, b: Int, c: Int): OptionIF<Pair<Int, Int>> {<br /> val ac: OptionIF<Int> = divide(a, c)<br /> return when (ac) {<br /> is None<Int> -> None<Pair<Int, Int>>()<br /> is Some<Int> -> {<br /> val bc: OptionIF<Int> = divide(b, c)<br /> when (bc) {<br /> is None<Int> -> None<Pair<Int, Int>>()<br /> is Some<Int> -> Some(Pair(ac.get(), bc.get()))<br /> else -> None<Pair<Int, Int>>()<br /> }<br /> }<br /> else -> None<Pair<Int, Int>>()<br /> }<br />}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />fun bindDivision(a: Int, b: Int, c: Int): OptionIF<Pair<Int, Int>> {<br /> return bind(divide(a, c)){(ac: Int) -> bind(divide(b, c)){(bc: Int) -> inject(Pair(ac, bc))}}<br />}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />fun main(args: Array<String>) {<br /> assertEquals(Some(Pair(2, 3)), division(18, 27, 9))<br /> assertEquals(None<Pair<Int, Int>>(), division(18, 27, 6))<br /> assertEquals(Some(Pair(2, 3)), bindDivision(18, 27, 9))<br /> assertEquals(None<Pair<Int, Int>>(), bindDivision(18, 27, 6))<br />}</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<span style="font-family: inherit;">Function
<b>division</b> threatens to march off to
the right side of the listing if it became any more complicated. It is very typical imperative code that is crying out for some refactoring.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">We can bring
the staircasing effect under control with <b>bind</b>.
Consider the implementation of <b>bindDivision</b>.
The outer call to <b>bind(divide(a, c)){ ac
-> ...}</b> has an <b>OptionIF</b> value
produced from the expression <b>divide(a,
c)</b>. Should this be a <b>Some</b> value,
then the function literal is called and its formal parameter <b>ac</b> is bound to the result from the <b>Some</b> value. In the inner call <b>bind(divide(b, c)){ bc -> ...}</b> the
inner function literal is called with the formal parameter <b>bc</b> bound to the <b>Some</b>
value produced from <b>divide(b, c)</b>. If
the two calls to <b>divide</b> both deliver
<b>Some</b> values then a final <b>Some</b> result is produced carrying the
pair we seek. If a <b>None</b> value is
delivered by either call to <b>divide</b>
then a <b>None</b> value is the final
result.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">This simplification is also present in the two following examples. Often we make lookups of a map data structure, a database or a web service and receive an optional response. In some scenarios we take the result of a first lookup and use it to perform a second lookup. Example 8a is an application based on a set of products differentiated by a unique code. The products are organized by country, city, supplier and code. A product stock is realized by overlapping maps.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The immutable <b>MapIF<K, V></b> trait and its <b>lookUpKey </b>member function provide the implementation. The function <b>getProductFrom </b>aims to deliver a <b>Product </b>given the </span>country, city, supplier and code, and the product stock:<br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun getProductFrom(country: String, ...,</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">productsByCountry: MapIF<String, MapIF<String, MapIF<String, MapIF<String, Product>>>>): OptionIF<Product></span><br />
<br />
<span style="font-family: inherit;">The product, if it exists, is obtained by making repeated <b>lookUpKey </b>function calls down through the nested maps. If anyone fails than we bail out with <b>None<Product></b>.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><b>Example 8a</b>: <i>Product searching</i></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example8a</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import kotlin.test.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.map.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">data class Product(val code: String, val name: String)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun getProductFrom(country: String, city: String, supplier: String, code: String, productsByCountry: MapIF<String, MapIF<String, MapIF<String, MapIF<String, Product>>>>): OptionIF<Product> {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val productsByCity: OptionIF<MapIF<String, MapIF<String, MapIF<String, Product>>>> = productsByCountry.lookUpKey(country)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> if (productsByCity.isDefined()) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val productsBySupplier: OptionIF<MapIF<String, MapIF<String, Product>>> = productsByCity.get().lookUpKey(city)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> if (productsBySupplier.isDefined()) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val productsByCode: OptionIF<MapIF<String, Product>> = productsBySupplier.get().lookUpKey(supplier)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> if (productsByCode.isDefined()) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return productsByCode.get().lookUpKey(code)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> } else</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return None<Product>()</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> } else</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return None<Product>()</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> } else</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return None<Product>()</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">// By country, by city, by supplier and by code</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">val productsByCountry: MapIF<String, MapIF<String, MapIF<String, MapIF<String, Product>>>> =</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "USA" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "San Francisco" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "Graham" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "SH" to Product("SH", "Shiraz"),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "ZI" to Product("ZI", "Zinfandel")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> ),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "France" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "Bordeaux" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "Jacques" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "SE" to Product("SE", "Saint Emilion"),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "ME" to Product("ME", "Medoc")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> ),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "Beaune" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "Marcel" to fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "AC" to Product("AC", "Aloxe-Corton"),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "ME" to Product("ME", "Mersault"),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "PO" to Product("PO", "Pommard"),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "SA" to Product("SA", "Savigny"),</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "VO" to Product("VO", "Volnay")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(Some(Product("PO", "Pommard")), getProductFrom("France", "Beaune", "Marcel", "PO", productsByCountry))</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(Some(Product("SH", "Shiraz")), getProductFrom("USA", "San Francisco", "Graham", "SH", productsByCountry))</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(None<Product>(), getProductFrom("France", "Beaune", "Marcel", "ZZ", productsByCountry))</span><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<div>
<br />
The implementation of function <b>getProductFrom </b>just does not look great. It looks ugly and not code you want to be associated with in your place of work.<br />
<br /></div>
<div>
However, since our <b>OptionIF<T></b> is monadic, we can sequence the <b>lookUpKey </b>calls much more gracefully. The implementation of the function <b>getProductFrom </b>in Example 8b is now much simpler and is reminiscent of the <b>bindDivision </b>function from Example 7.</div>
<div>
<br /></div>
<div>
<b>Example 8b</b>: <i>Product searching</i></div>
<div>
<br /></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example8b</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />import kotlin.test.*<br />import com.adt.kotlin.data.immutable.option.*<br />import com.adt.kotlin.data.immutable.map.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />data class Product(val code: String, val name: String)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />fun getProductFrom(country: String, city: String, supplier: String, code: String, productsByCountry: MapIF<String, MapIF<String, MapIF<String, MapIF<String, Product>>>>): OptionIF<Product> {<br /> return bind(productsByCountry.lookUpKey(country)) {productsByCity -><br /> bind(productsByCity.lookUpKey(city)){productsBySupplier -><br /> bind(productsBySupplier.lookUpKey(supplier)){productsByCode -><br /> productsByCode.lookUpKey(code)<br /> }<br /> }<br /> }<br />}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />// By country, by city, by supplier and by code<br />val productsByCountry: MapIF<String, MapIF<String, MapIF<String, MapIF<String, Product>>>> = ...</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br />fun main(args: Array<String>) {<br /> assertEquals(Some(Product("PO", "Pommard")), getProductFrom("France", "Beaune", "Marcel", "PO", productsByCountry))<br /> assertEquals(Some(Product("SH", "Shiraz")), getProductFrom("USA", "San Francisco", "Graham", "SH", productsByCountry))<br /> assertEquals(None<Product>(), getProductFrom("France", "Beaune", "Marcel", "ZZ", productsByCountry))<br />}</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<span style="font-family: inherit;">Alongside the <b>OptionIF<T></b> trait and its concrete classes <b>None<T></b> and <b>Some<T></b> there are a number of package level utility functions that make working with options very easy and natural. The </span><b>sequenceM </b>function combines a list of monadic options into one option monad that has a list of the results of those options inside it:<br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun <T> sequenceM(bs: ListIF<OptionIF<T>>): OptionIF<ListIF<T>></span><br />
<br />
Example 9 demonstrates how this might be used. Consider we have a <b>MapIF<String, Int></b> for the frequency distribution of words in a document, and a <b>ListIF<String></b> of words whose total occurrences we wish to obtain.<br />
<br />
<b>Example 9</b>: <i>Utility function sequenceM</i><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example9</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import kotlin.test.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.list.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.map.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">val frequencies: MapIF<String, Int> = fromSequence(</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "software" to 5,</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "engineering" to 3,</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "kotlin" to 9,</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "object" to 8,</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "oriented" to 3,</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "functional" to 3,</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> "programming" to 20</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">val words: ListIF<String> = fromSequence("object", "functional")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun getWordFrequencies(words: ListIF<String>, frequencies: MapIF<String, Int>): ListIF<OptionIF<Int>> =</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> words.map{(word: String) -> frequencies.lookUpKey(word)}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun distributions(frequency: ListIF<OptionIF<Int>>): Int {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fun ListIF<Int>.sum(): Int = this.foldLeft(0){(res: Int) -> {(elem: Int) -> res + elem}}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val freq: OptionIF<ListIF<Int>> = sequenceM(frequency)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return freq.getOrElse(emptyList<Int>()).sum()</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val wordFrequencies: ListIF<OptionIF<Int>> = getWordFrequencies(words, frequencies)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val dist: Int = distributions(wordFrequencies)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> assertEquals(11, dist)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<div>
<br /></div>
<div>
Given the <b>words </b>and the <b>frequencies </b>the function <b>getWordFrequencies </b>maps each word into a <b>ListIF </b>of <b>OptionIF<Int></b> through application of the <b>lookUpKey </b>member function. The function <b>distributions </b>then finds the total occurences in the <b>ListIF<Int></b> (wrapped in an <b>OptionIF</b>) obtained from <b>sequenceM</b>. Note that if any of the <b>OptionIF<Int></b> in the <b>ListIF </b>passed to <b>sequenceM </b>is a <b>None<Int></b> then a <b>None<ListIF<Int>></b> is returned.</div>
<div>
<br /></div>
<span style="font-family: inherit;">The <b>OptionIF<T></b> provides a type for representing optional values. It also acted as a vehicle for demonstrating powerful abstractions that can hide mundane implementation details. Using higher order abstractions such as higher order functions, monads, etc. we can simplify the implementation of function bodies. </span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">These observations have inspired me to reconsider how I implement function logic. I aim to reduce the complexity of function bodies by reducing or removing my use of control structures such as if statements nested in while statements, representative of much of my existing imperative code. By presenting function bodies as simple sequential actions they are much easier to write and much easier to reason about their correctness. Functions that are much more trustworthy. Functions such as <b>bindDivision </b>and <b>distributions </b>are simple illustrations of what I seek to achieve.</span><br />
<span style="font-family: inherit;"><br /></span>
Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-49001921047627573572014-02-14T07:14:00.000-08:002014-02-14T07:14:02.475-08:00Kotlin: An Option type #1<span style="font-family: inherit;">This pair of blogs introduces the Kotlin <b>Option </b>type that allows the programmer to specify where something is present or absent. It can be used in place of <b>null </b>to denote absence of a result. The <b>Option </b>type offers more than a new data type: more powerful abstractions, such as higher order functions, that hide many of the details of mundane operations such as mapping a function across a data type. We get to focus on the <i>what</i>, not the <i>how</i> making our code more <i>declarative</i>: incentivizing us to make our code blocks simpler.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Probably all Java developers have experienced a <b>NullPointerException</b>. Usually this occurs because some function returns it when not expected and when not dealing with that possibility in your client code. The value <b>null </b>is also used to represent the absence of a value such as when performing the member function <b>get </b>on a <b>Map</b>.</span><br />
<br />
Kotlin, of course, allows you to work safely with <b>null</b>. The null-safe operator for accessing properties is <span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">foo?.bar?.baz</span> will not throw an exception if either <b>foo </b>or its <b>bar </b>property is <b>null</b>. Instead, it returns <b>null </b>as its result.<br />
<br />
An alternative approach that seeks to reduce the need for <b>null </b>is to provide a type for representing optional values, i.e. values that may be present or not: the <b>OptionIF<T></b> trait. By stating that a value may or mat not be present <i>on the type level</i>, you and other developers are required by the compiler to deal with this possibility. Further, by providing various combinators we can chain together function calls on option values.<br />
<br />
Kotlin <b>OptionIF<T></b> is a container for zero or one element of a given type. An <b>OptionIF<T></b> can be either a <b>Some<T></b> wrapping a value of type <b>T</b>, or can be a <b>None<T></b> which represents a missing value. You create an <b>OptionIF<T></b> by instantiating the <b>Some </b>or <b>None </b>classes:<br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">val name: OptionIF<String> = Some("Ken Barclay")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">val absentName: OptionIF<String> = None<String>()</span><br />
<br />
<div>
Given an instance of <b>OptionIF<T></b> and the need to do something with it, how is this done? One way would be to check if a value is present by means of the <b>isDefined </b>member function, and if that is the case obtain the value with the <b>get </b>member function. This is shown in Example 1.</div>
<div>
<br /></div>
<div>
<b>Example 1</b>: <i>Accessing options</i></div>
<div>
<br /></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example1</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val op: OptionIF<Int> = Some(5)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> if (op.isDefined())</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> println("op: ${op.get()}") // => op: 5</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span></div>
<div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Deliberately, I have chosen to include types explicitly as an aid to the reader. Of course, Kotlin's type inferencing would allow me to omit some and, in turn, make the code more compact.</span><br />
<span style="font-family: inherit;"><br /></span></div>
The most common way to take optional values apart is through a pattern match. Example 2 introduces the <b>show </b>function which pattern matches on the <b>OptionIF </b>parameter and for a <b>Some </b>instance the member function <b>get </b>is used to retrieve the enclosed value.<br />
<br />
<b>Example 2</b>: <i>Pattern matching options</i><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example2</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun show(op: OptionIF<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> when (op) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> is Some<*> -> println(op.get())</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> else -> println("Missing")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> }</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val name: OptionIF<String> = Some("Ken Barclay")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val absentName: OptionIF<String> = None<String>()</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> show(name) // => Ken Barclay</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> show(absentName) // => Missing</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<div>
<br /></div>
<span style="font-family: inherit;">If you think this is clunky and expect something more elegant from Kotlin <b>OptionIF<T></b> you are correct. If you use the member function <b>get</b>, you may forget about checking with <b>isDefined </b>leading to a runtime exception, and this scenario is no different from using <b>null</b>. You should avoid using options this way. One simple improvement we can make to these use cases is provided by the <b>getOrElse </b>member function as shown in Example 3.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><b>Example 3</b>: <i>Provide a default</i></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example3</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val name: OptionIF<String> = Some("Ken Barclay")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val absentName: OptionIF<String> = None<String>()</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> println(name.getOrElse("Missing")) // => Ken Barclay</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> println(absentName.getOrElse("Missing")) // => Missing</span><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<div>
<br /></div>
I suggested that we consider an option as a collection of zero or one elements. Consequently it is provided with many of the behaviors we associate with containers such as filtering, mapping and folding. Example 4 illustrates transforming an <b>OptionIF<String></b> into an <b>OptionIF<Int></b>. When you map an <b>OptionIF<String></b> that is a <b>None<String></b> then you get a <b>None<Int></b>.<br />
<br />
<b>Example 4:</b> <i>Mapping</i><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example4</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val name: OptionIF<String> = Some("Ken Barclay")</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val absentName: OptionIF<String> = None<String>()</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> println(name.map{(str: String) -> str.length()}.getOrElse(0)) // => 11</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> println(absentName.map{str -> str.length()}.getOrElse(0)) // => 0</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span><br />
<div>
<br />
The member function <b>map </b>is a <i>higher order function</i>, accepting a transformer function as parameter. Using customizable higher order functions allows us to think about solutions differently. Function <b>map</b> allows us to apply a generic operation to the data type and means we can focus on the result.<br />
<br /></div>
<div>
A somewhat more elaborate illustration is given in Example 5 which implements a repository of users. We need to be able to find a user by their unique id. A request made with a non-existent id suggests a return type of <b>OptionIF<User></b>.</div>
<div>
<br /></div>
<div>
<b>Example 5</b>: <i>User repository</i></div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">package example5</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">import com.adt.kotlin.data.immutable.option.*</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">class User(val id: Int, val firstName: String, val lastName: String, val age: Int)</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">class UserRepository {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> fun findById(id: Int): OptionIF<User> {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> return if (users.containsKey(id)) {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val user: User = users.get(id)!!</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> Some(user)</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> } else</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> None<User>()</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">// ---------- properties ----------------------------------</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val users: Map<Int, User> = hashMapOf(</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> 1 to User(1, "Ken", "Barclay", 25),</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> 2 to User(2, "John", "Savage", 31)</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> )</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">fun main(args: Array<String>) {</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val repository: UserRepository = UserRepository()</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val user: OptionIF<User> = repository.findById(1)</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> val userName: OptionIF<String> = user.map{u -> "${u.firstName} ${u.lastName}"}</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> if (userName.isDefined())</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"> println("User: ${userName.get()}") // => User: Ken Barclay</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;">}</span></div>
</div>
<div>
<br /></div>
<div>
Our dummy implementation uses a <b>HashMap</b>. Perhaps we might develop a <b>Map<K, V></b> implementation with a <b>lookUpKey </b>member function that returns an <b>OptionIF<V></b>.</div>
<div>
<br /></div>
<div>
In the follow-on blog I will consider some more advanced use-cases with <b>OptionIF<T></b>. I aim to show how more powerful abstractions over the <b>OptionIF<T></b> type can reduce the complexity of functions, encouraging us to cede control to these abstractions and remove the need to code each atomic step in an algorithm.</div>
<div>
<br /></div>
<div style="background-color: #f8f8f8; border: 0px; color: #222222; line-height: 27.59375px; margin-bottom: 1.5em; padding: 0px; vertical-align: baseline;">
<br /></div>
Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com3tag:blogger.com,1999:blog-3255923023602927617.post-72779600308317654742012-06-21T06:36:00.004-07:002012-06-21T06:36:33.489-07:00function(groovy) #5<br />
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Arial","sans-serif"; font-size: 14.0pt;">function(groovy) #5<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">If all you have is a hammer, everything looks like a nail.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Abstract: One of the
challenges of a new paradigm is learning to think in an entirely new way. The ability
to pass code as a parameter introduces a new style to the imperative
programmer. A declarative style abstracts out generic pieces of machinery and
customizes them via higher-order functions.<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Ken Barclay<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">kenbarc@googlemail.com<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Previous</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">: <a href="http://kenbarclay.blogspot.co.uk/2012/06/functiongroovy-4.html" target="_blank">The iterator methods</a><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Resources</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">: <a href="https://docs.google.com/document/pub?id=1ktHRAFrDnPDe3RhHK_RqAs1Ou-kxIWphnur63cmoX1A" target="_blank">Chapter 12 Higher Order Functions</a><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Arial","sans-serif"; font-size: 14.0pt;">The iterator functions<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Many
functions to perform functional style <b>List</b>
manipulation are defined as static methods and closures in the <i>companion class</i> <b>GListF</b>. The class is defined as abstract so there is no intention
of creating an instance. It simply acts as a repository for these useful
functions. The arrangement is not unlike the latest Groovy extension methods.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">For example, this class defines the function <b>map</b> that transforms a list of values in
the manner of the GDK's <b>collect</b>
method using a function as its transformer. The <b>map</b> function is provided in two flavors: a curried form and an
uncurried form. Of course, the function <b>C</b>
is used to define the curried version from its uncurried version. The curried
version is given the suffix C in its name:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">/**<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * Function map takes two parameters: a
function and a list. Function map<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> *
applies the function parameter to each item in the list, delivering<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * a
new list.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> *<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * map:: (X -> Y) * [X] -> [Y]<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * mapC:: (X -> Y) -> [X] -> [Y]<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * @param fxy pure function:: X -> Y<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * @param ys existing list<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> * @return new list of transformed values<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> */<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">private
static final <X, Y> List<Y> _map(final Closure<Y> f, final
List<X> xs) { xs.collect(f) }<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">public
static final map = GListF.&_map<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">public
static final mapC = C(map)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">For most applications function <b>map</b> will suffice. However, in some advanced examples we will find
we wish to call <b>mapC</b> with its single
function parameter.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Observe how the behavior is first defined with the <b>_map</b> method. The closures <b>map</b> and <b>mapC</b> are defined from it. The <b>&.</b>
operator is </span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">used to get a reference to a
method, and from it create a reference to a closure. The aim of this scheme is
to define the <b>_map</b> method with the
generic type parameters <b>X</b> and <b>Y</b>. Including both the parameter type
and result type fully documents the values involved in using this method.
Groovy does not support generic type parameters when defining closures and so
this approach circumvents this limitation. A Groovy static type checker would
assist greatly.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">All the methods/closures defined in
<b>GListF</b> present the Groovy list with
an immutable interface. As a consequence, some of the operations are not
especially efficient. This issue is revisited in a later blog where we
implement a more efficient immutable list. Notwithstanding this, we can begin
presenting solutions that are more declarative than would be possible using
Groovy lists directly.</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;"><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Arial","sans-serif"; font-size: 12.0pt;">Mapping<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">The
GDK's </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">collect</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> iterator method is used
to iterate through the elements of the receiving list object and transforms each element into a new value
using the closure parameter as a transformer, returning a </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-bidi-font-weight: bold;">list</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-weight: bold;"> of transformed values.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">A
pictorial representation of how </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">map</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> behaves is shown in
Figure 5.1. On the left we show some function (closure) </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">f</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> which when applied to a single parameter
(represented by the circle) delivers a value (the square). Now, if we have a l</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">ist</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> of values of type circle,
then </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">map f list</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> delivers a l</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">ist</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> of values of type square
produced by applying </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">f</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> to each of the originals.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Figure 5.1</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>Application
of </i></span><i><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">map</span></i><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-size: 10.0pt; mso-fareast-language: EN-GB; mso-no-proof: yes;"><v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f">
<v:stroke joinstyle="miter">
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0">
<v:f eqn="sum @0 1 0">
<v:f eqn="sum 0 0 @1">
<v:f eqn="prod @2 1 2">
<v:f eqn="prod @3 21600 pixelWidth">
<v:f eqn="prod @3 21600 pixelHeight">
<v:f eqn="sum @0 0 1">
<v:f eqn="prod @6 1 2">
<v:f eqn="prod @7 21600 pixelWidth">
<v:f eqn="sum @8 21600 0">
<v:f eqn="prod @7 21600 pixelHeight">
<v:f eqn="sum @10 21600 0">
</v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:formulas>
<v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f">
<o:lock aspectratio="t" v:ext="edit">
</o:lock></v:path></v:stroke></v:shapetype><v:shape id="Picture_x0020_3" o:spid="_x0000_i1026" style="height: 236.25pt; mso-wrap-style: square; visibility: visible; width: 409.5pt;" type="#_x0000_t75">
<v:imagedata o:title="" src="file:///C:\Users\Ken\AppData\Local\Temp\msohtmlclip1\01\clip_image001.png">
</v:imagedata></v:shape></span><span style="font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">As
we noted, the companion class <b>GListF</b>
contains a rich selection of functions (static closure definitions) for
processing lists. Example 5.1 revisits the previous example, this time using
the <b>mapC</b> function from <b>GListF</b>.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example 5.1</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>Curried
map</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">import static
com.adt.groovy.data.immutable.list.GListF.mapC<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // multiply:: Integer * Integer ->
Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final multiply = {
final int x, final int y -> x * y}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // twice:: Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final twice =
multiply.curry(2)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // quadruple:: Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final quadruple =
multiply.curry(4)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // twiceAll:: [Integer] -> [Integer]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final twiceAll =
mapC(twice)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // quadrupleAll:: [Integer] -> [Integer]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final quadrupleAll =
mapC(quadruple)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Integer> numbers = [1, 2, 3, 4]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
twiceAll(numbers) == [2, 4, 6, 8]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
quadrupleAll(numbers) == [4, 8, 12, 16]<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">It
is relatively easy to prove that map(f </span><span style="font-family: "Arial","sans-serif"; font-size: 10.0pt;">●</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> g, xs) = (map f </span><span style="font-family: "Arial","sans-serif"; font-size: 10.0pt;">●</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> map g)(xs), where </span><span style="font-family: "Arial","sans-serif"; font-size: 10.0pt;">● represents function composition</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">. Applying f </span><span style="font-family: "Arial","sans-serif"; font-size: 10.0pt;">●</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> g to every element of a
list is the same as applying g to every member of the list and then applying f
to every member of the resulting list. The equality demonstrates how we might <i>refactor</i> our code to make it more
efficient. If our code includes (map f </span><span style="font-family: "Arial","sans-serif"; font-size: 10.0pt;">●</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> map g) then we optimize it with map(f </span><span style="font-family: "Arial","sans-serif"; font-size: 10.0pt;">●</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> g). The former makes one
pass across the initial list then a second pass across the result list. The
latter makes only a single pass across the initial list reducing the amount of
work to be done. This equality is demonstrated in Example 5.2.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example 5.2</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>Map
composition equality</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">import static
com.adt.groovy.data.immutable.list.GListF.mapC<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">import static
com.adt.groovy.data.immutable.list.GListF.map<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // twice:: Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final twice = { final
int x -> 2 * x}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // successor:: Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final successor = {
final int x -> 1 + x}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // composeTwiceSuccessor:: Integer ->
Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
composeTwiceSuccessor = twice >> successor<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // composeMapTwiceMapSuccessor:: [Integer]
-> [Integer]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final composeMapTwiceMapSuccessor
= mapC(twice) >> mapC(successor)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Integer> numbers = [1, 2, 3, 4]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
map(composeTwiceSuccessor, numbers) == composeMapTwiceMapSuccessor(numbers)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">The
function <b>composeTwiceSuccessor</b>
transforms an <b>Integer</b> into another <b>Integer</b>. The left side of the <b>assert</b> applies this transformation to
the list of numbers. On the right side of the <b>assert</b> the function <b>composeMapTwiceMapSuccessor</b>
first doubles the values in the <b>numbers</b>
list, then increments by one the values in the resulting list.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Arial","sans-serif"; font-size: 12.0pt;">Filtering<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">It
is also common to select all the elements from a list with some given property.
For example we might wish to choose only those overdrawn bank accounts from a
list of accounts. We usually describe this as <i>filtering</i>. Example 5.3 introduces the higher order function </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">filter</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> in which the selection
criterion is specified by the function parameter. The selection function is
sometimes known as a <i>predicate</i> ― a
function returning a </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Boolean</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> value which describes whether the criterion has
been met.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example 5.3</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>The filter
function</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">import static
com.adt.groovy.data.immutable.list.GListF.filter<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // isEven:: Integer -> Boolean<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final isEven = { final
int x -> (x % 2 == 0)}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Integer> numbers = [11, 12, 13, 14]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert filter(isEven,
numbers) == [12, 14]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert filter(isEven,
[]) == []<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">def bk1 = new
Book(title: 'Groovy Programming', author: 'Barclay', price: 22.90, category:
'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">def bk2 = new
Book(title: 'Groovy in Action', author: 'Konig', price: 32.00, category:
'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">def bk3 = new
Book(title: 'Grails', author: 'Rocher', price: 29.00, category: 'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">def bk4 = new
Book(title: 'Thinking in Java', author: 'Eckel', price: 24.50, category:
'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">def List<Book>
books = [bk1, bk2, bk3, bk4]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert filter({bk
-> (bk.price < 25.00)}, books) == [bk1, bk4]<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">The GDK's iterator method <b>findAll</b>
is used to implement the <b>filter</b>
function.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Earlier we showed how proving equality of two
mappings can lead to more efficient programs. We can also show that:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">filter p ● map f = map
f ● filter(p ● f)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">The
equation says that a <b>map</b> followed by
a <b>filter</b> can be replaced by a <b>filter</b> followed by a <b>map</b>. The right side is potentially more
efficient than the left since the <b>map</b>
could be applied to a shorter list. This is demonstrated by Example 5.4.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example 5.4</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>Maps and
filters</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">import static
com.adt.groovy.data.immutable.list.GListF.filterC<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">import static
com.adt.groovy.data.immutable.list.GListF.mapC<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // isWrittenBy:: String -> Book ->
Boolean<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final isWrittenBy = {
final String auth -> { final Book book -> (book.author == auth)}}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;"> // priceIncrease:: BigDecimal -> Book
-> Book<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final priceIncrease =
{ final BigDecimal amount -> { final Book book -> new Book(title: book.title,
author: book.author, price: book.price + amount, category: book.category)}}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final mapThenFilter =
mapC(priceIncrease(2.00)) >> filterC(isWrittenBy('Ken Barclay'))<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final filterThenMap =
filterC(priceIncrease(2.00) >> isWrittenBy('Ken Barclay')) >>
mapC(priceIncrease(2.00))<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final book1 = new
Book(title: 'Groovy Programming', author: 'Ken Barclay', price: 20.45,
category: 'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final book2 = new
Book(title: 'Groovy in Action', author: 'Dierk Konig', price: 32.00, category:
'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final book3 = new
Book(title: 'Object Oriented Design', author: 'Ken Barclay', price: 25.50,
category: 'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final book4 = new
Book(title: 'Programming Groovy', author: 'Venkat Subramaniam', price: 29.50,
category: 'CompSci')<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final List<Book>
books = [book1, book2, book3, book4]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
mapThenFilter(books) == filterThenMap(books)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoBodyText">
<span style="font-family: "Comic Sans MS"; mso-bidi-font-style: normal;">Figure 5.2 describes the </span><b><span style="font-family: "Comic Sans MS"; mso-bidi-font-family: Arial; mso-bidi-font-style: normal;">filter</span></b><span style="font-family: "Comic Sans MS"; mso-bidi-font-style: normal;"> closure. If </span><b><span style="font-family: "Comic Sans MS"; mso-bidi-font-family: Arial; mso-bidi-font-style: normal;">p</span></b><span style="font-family: "Comic Sans MS"; mso-bidi-font-style: normal;"> represents some predicate function (closure, returning a boolean
value), then when applied to a triangle it delivers true and when applied to a
square it produces false. Now </span><b><span style="font-family: "Comic Sans MS"; mso-bidi-font-family: Arial; mso-bidi-font-style: normal;">filter p list</span></b><span style="font-family: "Comic Sans MS"; mso-bidi-font-style: normal;"> delivers a new </span><span style="font-family: "Comic Sans MS"; mso-bidi-font-family: Arial; mso-bidi-font-style: normal;">list</span><span style="font-family: "Comic Sans MS"; mso-bidi-font-style: normal;"> containing only
those triangles that satisfy the predicate.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Figure 5.2</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">:
<i>Application of filter</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<v:shape id="Picture_x0020_4" o:spid="_x0000_i1025" style="height: 199.5pt; mso-wrap-style: square; visibility: visible; width: 415.5pt;" type="#_x0000_t75">
<v:imagedata o:title="" src="file:///C:\Users\Ken\AppData\Local\Temp\msohtmlclip1\01\clip_image002.png">
</v:imagedata></v:shape><span style="font-family: "Comic Sans MS"; mso-bidi-font-family: Arial;"><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Arial","sans-serif"; font-size: 12.0pt;">Folding<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">It
is also common to reduce a collection to a single value. For example we might
wish to sum or multiply all the elements in a list. </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-fareast-language: EN-GB;">This
is the basis for a particular kind of higher order function called <i>folding</i>. Folding is used to fold a
function (such as a summation) into a list of values.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">The
<i>fold</i> function reduces a list to a single value by "folding" a
binary operator between successive elements of the list. For example, consider
we have the list [x1, x2, x3, ..., xn], an initial value e, and the binary
operator □, then:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">fold □ e [x1, x2, x3, ..., xn] = e □ x1 □ x2 □ x3 □ ... □ xn<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">The <b>fold</b> function takes a binary function □, together with an initial
value e and a list. Notice that the version of fold above is left-associative.
In other words, the result it produces is equivalent to doing:<o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div class="MsoNormal" style="margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-fareast-language: EN-GB;">( ... (((e </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">□ x1) □ x2) □ x3) ... □
xn)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-fareast-language: EN-GB;">Example
5.5 introduces the function </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-fareast-language: EN-GB;">foldLeft</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-fareast-language: EN-GB;"> implemented using the
GDK's </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-fareast-language: EN-GB;">each</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-fareast-language: EN-GB;"> iterator method</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-fareast-language: EN-GB;">.
It has three parameters: the binary function to be folded in, the initial value
when starting the folding, and the list of values. The type signature for the
function given as:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">/**<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * foldLeft is a higher-order
function that folds a binary function into a<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * list of values. Effectively:<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> *<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * foldLeft(f, e, [x1, x2, ..., xn]) = (...((e
f x1) f x2) f...) f xn<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> *<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * foldLeft:: (Y -> X -> Y)
* Y * [X] -> Y<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * foldLeftC:: (Y -> X -> Y)
-> Y -> [X] -> Y<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * <o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * @param f pure binary function:: Y -> X -> Y<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * @param e initial value<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * @param xs existing list<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> * @return folded result<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> */<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">private static final <X, Y> Y _foldLeft(final Closure<Y> f,
final Y e, final List<X> xs) {<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> Y res = e<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> xs.each{ x -> res = f(res)(x)
}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> return res<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">public static final foldLeft = GListF.&_foldLeft<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">public static final foldLeftC = C3(foldLeft)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-fareast-language: EN-GB;">Note
that the function parameter is expected in its curried form. The function
parameter combines a Y and an X to produce a Y. The initial value for <b>foldLeft</b> is of type Y and is combined
with the first member of the list. The result of type Y is then combined with
the second member of the list, and so on. Ultimately, a Y value is delivered.
The companion class <b>GListF</b> includes
the two variants <b>foldLeft</b> and <b>foldLeftC</b>.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-fareast-language: EN-GB;">Example 5.5</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-fareast-language: EN-GB;">:
<i>The foldLeft function</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">import static com.adt.groovy.fp.FunctionF.C<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">import static
com.adt.groovy.data.immutable.list.GListF.appendC<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">import static
com.adt.groovy.data.immutable.list.GListF.foldLeft<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> // add::
Integer * Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final add = { final int x -> { final int y ->
x + y }}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final List<Integer> numbers = [11, 12, 13,
14]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final int sum = foldLeft(add, 0, numbers)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">assert sum == 50<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> //
logicalAnd:: Boolean -> Boolean -> Boolean<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final logicalAnd = { final boolean x -> { final
boolean y -> x && y }}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final List<Boolean> truthful = [true, true,
true]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final boolean allTruthful = foldLeft(logicalAnd,
true, truthful)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">assert allTruthful == true<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final List<Integer> flatten =
foldLeft(appendC, [], [[1, 2, 3], [4, 5], [6]])<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">assert flatten == [1, 2, 3, 4, 5, 6]<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-fareast-language: EN-GB;">Folding is a surprisingly fundamental operation.
Its generality allows us to define many standard list processing operations.
Example 5.6 defines the primitive operation <b>reverse</b> in terms of a left fold. The initial value given to <b>foldLeft</b> is the empty list [] into
which the reversed list is assembled. The binary function required by <b>foldLeft</b> must then have the signature
[X] -> X -> [X] where the second parameter is prepended on to the list
first parameter. Of course <b>consC</b>
does just this but has its parameter in the opposite order. Functions <b>flip</b> and <b>flipC</b> performs the necessary transformation, converting the
function X -> Y -> Z to Y -> X -> Z.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-fareast-language: EN-GB;">Example 5.6</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial; mso-fareast-language: EN-GB;">: <i>Folding and
primitive operations</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">import static com.adt.groovy.fp.FunctionF.flipC<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">import static com.adt.groovy.data.immutable.list.GListF.consC<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">import static com.adt.groovy.data.immutable.list.GListF.foldLeft<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;"> // reverse:: [A] -> [A]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">final reverse = {xs -> foldLeft(flipC(consC), [], xs)}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">assert reverse([1, 2, 3, 4]) == [4, 3, 2, 1]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt; mso-fareast-language: EN-GB;">assert reverse(['Ken', 'John', 'Jessie']) == ['Jessie', 'John', 'Ken']<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">These examples illustrate how the functional style
gives us new and different building blocks. Some of the examples used the
curried variants <b>mapC</b> and <b>filterC</b> to produce specialist
processing functions. No new code had to be developed other than the closure
parameters. The curried forms are our factories for functions.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">The examples also show a reduced use of control
flow such as for statements. This offers many advantages. First, the code is
easier to read and write. That means it will be easier to reason about its
correctness. Control flow statements are usually accompanied by state variables
that are updated. In its place we see code in which we sequentially bind
results to identifiers then finish the code with the resulting expression.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">These extension methods are not, in some cases.
especially efficient. For example, the <b>concatenate</b>
method produces a new list by joining together two existing lists. Immutable
data structures, the subject of the next blog, can offer a solution.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com2tag:blogger.com,1999:blog-3255923023602927617.post-55089893244472394442012-06-04T09:31:00.002-07:002012-06-04T09:31:56.336-07:00function(groovy) #4<br />
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Arial","sans-serif"; font-size: 14.0pt;">function(groovy) #4<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">If all you have is a hammer, everything looks like a nail.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Abstract: The iterator
methods on the collection classes take a higher order closure as a parameter.
But they achieve much more when we recognize that we are relinquishing control
over iteration in return for a general mechanism for use with collection
frameworks. Higher order functions allow us to raise the abstraction level at
which we operate.<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Ken Barclay<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">kenbarc@googlemail.com<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Previous</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">: <a href="http://kenbarclay.blogspot.co.uk/2012/05/functiongroovy-3.html" target="_blank">Advanced closure</a><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Resources</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">: <a href="https://docs.google.com/document/pub?id=15BFf8-sw6lngAsTFtOLiYrC8z0qRG1qDoBHMXoVCW9c" target="_blank">Chapter 11 Closures</a><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Arial","sans-serif"; font-size: 14.0pt;">The iterator methods<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Table
4.1 lists some of the <i>iterator methods</i>
that can be used with the collection classes such as <b>List</b> and <b>Map</b>. Excepting
method </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">inject</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">, all these methods are effectively
defined on the Groovy </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Object</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> class. The </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">inject</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> method is defined in the </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Collection</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> class. Not all of the
iterator methods are illustrated. For details of these and other methods see
the Groovy documentation.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Table 4.1</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>Iterator
methods</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid black .5pt; mso-border-insideh: .5pt solid black; mso-border-insidev: .5pt solid black; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="background: #E0E0E0; border: solid black 1.0pt; mso-border-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Name<o:p></o:p></span></div>
</td>
<td style="background: #E0E0E0; border-left: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Signature/description<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">any<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">boolean any(Closure predicate)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Iterates
over every element of </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">this</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> collection, and check that the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">predicate</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
is valid for at least one element.<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">collect<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">List collect(Closure transformer)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Iterates
through </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">this</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> collection transforming each element into a new
value using the closure as a </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">transformer</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">, returning a new </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">List</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
of transformed values.<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">each<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">void each(Closure action)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Iterate
through </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">this</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> object and execute the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">closure</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">.<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">eachWithIndex<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">void eachWithIndex(Closure action)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Iterate
through </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">this</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> object and execute the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">closure</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
with a counter.</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;"><o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">every<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">boolean every(Closure predicate)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Iterates
over every element of </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">this</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> collection, and check that the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">predicate</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
is valid for all elements.<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">find<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Object find(Closure predicate)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Find the
first value matching the condition defined by the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">predicate</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
closure. If no match is found, then return </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">null</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">.<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">findAll<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">List findAll(Closure predicate)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Find all
the values matching the condition defined by the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">predicate</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
closure. If no match is found, then return the empty </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">List</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">.</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;"><o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">grep<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">List grep(Object filter)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Iterate
over every element of </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">this</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> collection and return each object that matches
the given </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">filter</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> – calling the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">isCase()</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> method.<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.45pt;" valign="top" width="121">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">inject<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid black 1.0pt; border-left: none; border-right: solid black 1.0pt; border-top: none; mso-border-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 336.0pt;" valign="top" width="448">
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Object inject(Collection collection, Object
init, Closure closure)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Iterates
through </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">this</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> collection, passing the </span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">init</span><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
value to the closure along with the first item. On subsequent iterations pass
the previous closure value and the next iterated item. Upon completion return
with the final closure value.<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">This
group of methods take a closure (or function) as parameter. They are usually
referred to as <i>higher order functions</i>.
This capability is important for a number reasons. Higher order functions means
that you can make assumptions how language elements will compose. Through this
you can eliminate entire categories of methods in a class hierarchy by building
general mechanisms that traverse structures such as lists and apply one or more
functions (closures) to each element. This is the subject of this blog,
illustrated with some examples.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> Example 4.1 shows method <b>collect</b> used with collections of people
and 2-dimensional points. Class <b>Person</b>
is defined with <b>name</b> and <b>age</b> properties. Class <b>Point</b> is defined with <b>x</b> and <b>y</b> properties and an implementation for the method <b>equals</b>. It also defines the method <b>moveBy</b> that produces a new <b>Point</b> instance with coordinates moved
by the displacement given as parameters.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example 4.1</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>Method
collect</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Person p1 = new
Person(name: 'Ken', age: 25)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Person p2 = new
Person(name: 'John', age: 31)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Person p3 = new
Person(name: 'Jessie', age: 22)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Person> people = [p1, p2, p3]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert people.collect{
p -> p.name } == ['Ken', 'John', 'Jessie']<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Point pt1 = new
Point(x: 2, y : 3)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Point pt2 = new
Point(x: 4, y : 5)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Point pt3 = new
Point(x: 8, y : 12)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Point> points = [pt1, pt2, pt3]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert points.collect{
p -> p.moveBy(1, 2) } == [new Point(x: 3, y: 5), new Point(x: 5, y: 7), new
Point(x: 9, y:14)]<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">The
<b>collect</b> method is better known by
the name <b>map</b> in the functional world
─ map some function across the elements of a collection.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> The </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">findAll</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
method is used to obtain the elements from a </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">List</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">
or </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Map</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> that match some criteria.
In either case a </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">List</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> of successes is returned.
If no such elements are found, then [] is returned. The criterion is specified
by a <i>predicate function</i>. For a </span><b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Map</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">, the predicate must be
defined in terms of one parameter, representing the map entry. Example 4.2
contains short illustrations. In the functional world this is usually known as <b>filter</b>.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example 4.2</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>The </i></span><i><span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">findAll</span></i><i><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;"> method<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Integer> numbers = [11, 12, 13, 14]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
numbers.findAll{ elem -> elem > 12 } == [13, 14]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
numbers.findAll{ elem -> elem > 14 } == []<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert ['John', 'Ken',
'Jessie'].findAll{ elem -> elem == 'Ken'} == ['Ken']<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Map<String,
Integer> staffTel = ['Ken' : 1234, 'John' : 5678, 'Jessie' : 9012]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
staffTel.findAll{entry -> entry.value > 5000}.collect{ elem ->
elem.key}.contains('Jessie')<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoBodyText">
<span style="font-family: "Comic Sans MS";">The </span><b><span style="font-family: "Comic Sans MS"; mso-bidi-font-family: Arial;">inject</span></b><span style="font-family: "Comic Sans MS";">
method iterates through a collection, passing the initial value to the closure
along with the first item of the collection. On subsequent iterations pass the
previous closure result and the next iterated item from the collection. Upon
completion of the iteration, return with the final closure value. Figure 4.1
describes the effect. First, the <b>init</b>
value is used to initialize the <b>res</b>
formal parameter of the closure. At the same time the first element from the <b>list</b> initializes the <b>elem</b> parameter. The final closure
expression returns a value that re-initializes the <b>res</b> parameter with the second <b>list</b>
element initializing the <b>elem</b>
parameter. The process continues until the final <b>list</b> element is processed and the return from the closure is
returned as the result of the <b>inject</b>
method.<o:p></o:p></span></div>
<div align="left" class="MsoBodyText" style="text-align: left;">
<br /></div>
<div align="left" class="MsoBodyText" style="text-align: left;">
<b><span style="font-family: "Comic Sans MS";">Figure 4.1</span></b><span style="font-family: "Comic Sans MS";">: <i>Description of the </i></span><i><span style="font-family: "Comic Sans MS"; mso-bidi-font-family: Arial;">inject</span></i><i><span style="font-family: "Comic Sans MS";"> method</span></i><span style="font-family: "Comic Sans MS";"><o:p></o:p></span></div>
<div align="left" class="MsoBodyText" style="text-align: left;">
<br /></div>
<div align="left" class="MsoBodyText" style="text-align: left;">
<span style="font-family: "Comic Sans MS"; mso-fareast-language: EN-GB; mso-no-proof: yes;"><v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f">
<v:stroke joinstyle="miter">
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0">
<v:f eqn="sum @0 1 0">
<v:f eqn="sum 0 0 @1">
<v:f eqn="prod @2 1 2">
<v:f eqn="prod @3 21600 pixelWidth">
<v:f eqn="prod @3 21600 pixelHeight">
<v:f eqn="sum @0 0 1">
<v:f eqn="prod @6 1 2">
<v:f eqn="prod @7 21600 pixelWidth">
<v:f eqn="sum @8 21600 0">
<v:f eqn="prod @7 21600 pixelHeight">
<v:f eqn="sum @10 21600 0">
</v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:f></v:formulas>
<v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f">
<o:lock aspectratio="t" v:ext="edit">
</o:lock></v:path></v:stroke></v:shapetype><v:shape id="Picture_x0020_1" o:spid="_x0000_i1025" style="height: 127.5pt; mso-wrap-style: square; visibility: visible; width: 351pt;" type="#_x0000_t75">
<v:imagedata o:title="" src="file:///C:\Users\Ken\AppData\Local\Temp\msohtmlclip1\01\clip_image001.png">
</v:imagedata></v:shape></span><span style="font-family: "Comic Sans MS";"><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example
4.3 shows the method <b>inject</b> used
with collections of people and points. The first assert uses method <b>inject</b> to sum the ages of the people.
In the second assert method <b>inject</b>
is used to create a <b>Map</b> of <b>People</b> instances indexed by their name.
In the third assert a <b>List</b> of the <b>x</b> values from the <b>List</b> of <b>Point</b>s is
produced. In the final assert a <b>List</b>
of the pairs of the <b>x</b> and <b>y</b> values from the <b>Point</b> instances is created. The pairs are presented as sub-lists of
length 2.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">Example 4.3</span></b><span style="font-family: "Comic Sans MS"; font-size: 10.0pt;">: <i>Collections
of people and 2D points</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Person p1 = new Person(name:
'Ken', age: 25)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Person p2 = new
Person(name: 'John', age: 31)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Person p3 = new
Person(name: 'Jessie', age: 22)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Person> people = [p1, p2, p3]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
people.inject(0){ res, p -> res += p.age } == 78<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert people.inject([:]){
res, p -> res[p.name] = p; res} == ['Ken': p1, 'John': p2, 'Jessie': p3]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Point pt1 = new
Point(x: 2, y : 3)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Point pt2 = new
Point(x: 4, y : 5)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final Point pt3 = new
Point(x: 8, y : 12)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">final
List<Point> points = [pt1, pt2, pt3]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<br /></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert points.inject([]){
res, p -> res += p.x } == [2, 4, 8]<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: #d9d9d9; background-position: initial initial; background-repeat: initial initial; margin: 0cm 0cm 0.0001pt 14.2pt;">
<span style="font-family: "Arial","sans-serif"; font-size: 9.0pt;">assert
points.inject([]){ res, p -> res.add([p.x, p.y]); res} == [[2, 3], [4, 5],
[8, 12]]<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">As we have shown, higher order functions means we
can eliminate entire categories of methods on a collection class hierarchy. We
build a general mechanism that traverses a collection and applies a higher
order function to each element. For example, the <b>collect</b> method expects a function parameter that describes how to
transform the elements of the collection. The <b>findAll</b> method expects a predicate closure that identifies the
elements to be selected.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">By comparison, re-implementing the examples in an
imperative style would mean deploying for statements or iterator controlled
while loops to manage the iteration. Further, we would be coding each atomic
step when implementing the algorithm, often with state.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: "Comic Sans MS"; font-size: 10.0pt; mso-bidi-font-family: Arial;">Relinquishing control over low-level details has
been a constant trend in software development. Memory management and garbage
collection are now given over to the runtimes. A functional or declarative
style continues this development, taking control over iteration as demonstrated.
Introducing a functional or declarative style as presented by the examples
means we spend less effort in solving a problem (the how) and more on the
processes (the what).<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0tag:blogger.com,1999:blog-3255923023602927617.post-12716873029963432982012-05-17T00:31:00.001-07:002012-05-17T00:31:30.006-07:00function(groovy) #3<br />
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: Arial, sans-serif; font-size: 14pt;">function(groovy) #3<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">If all you have is a hammer, everything looks like a nail.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<i><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Abstract: The Groovy
closure can be the return value from a method or another closure. This idea
eases us into the world of higher order functions: functions that accept
functions as parameters or return functions as their result. Functions as
parameters is the key feature of the next blog. Functions as return values
introduces the notion of currying and increasing the adoption of functions with
only a single parameter.<o:p></o:p></span></i></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Ken Barclay<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">kenbarc@googlemail.com<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Previous</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">: <a href="http://kenbarclay.blogspot.co.uk/2012/05/functiongroovy-2.html" target="_blank">The Groovy closure</a><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Resources</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">: <a href="https://docs.google.com/document/pub?id=1ktHRAFrDnPDe3RhHK_RqAs1Ou-kxIWphnur63cmoX1A" target="_blank">Chapter 12 Higher Order Functions</a><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<b><span style="font-family: Arial, sans-serif; font-size: 14pt;">Advanced closures<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">A
single function definition can effectively define a complete family of
functions. Having defined the parent function, we are able to specialize from
this single parent a number of related functions. To achieve this we use the
notion of <i>currying</i>, named after the
mathematician Haskell Curry. This idea is generally unfamiliar to the
imperative programmer but is one worth getting acquainted with.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Example
3.1 demonstrates how the <b>Closure</b>
class method </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">curry</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> is used to achieve the
effect of currying. Closure </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">multiply</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> expects two parameters
and returns their product. If we </span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">curry</span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> this function with the
value 2, then we have created a new function which doubles its single
parameter. Sensibly we choose to refer to this as </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">twice</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">.
Equally, if we </span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">curry</span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> <b>multiply</b>
with the value 4, then we have the closure </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">quadruple</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">.
Both are functions of one parameter and can be used directly, or are candidates
for use with any other function.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Example 3.1</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">: <i>Curried closure</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // multiply:: Integer * Integer ->
Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final
multiply = { final int x, final int y -> x * y }<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // twice:: Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final twice
= multiply.curry(2)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // quadruple:: Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final
quadruple = multiply.curry(4)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
twice(5) == 10<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
quadruple(5) == 20<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">The
type signature informs us that </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">multiply</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> is a function which when
given a pair of </span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">integers</span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> will return their product. If then we were able
to call function </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">multiply</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> and give only one actual
parameter, then we would get a result which is itself another function. For
example, if we could call </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">multiply</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> with the parameter 2,
then effectively the first formal parameter </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">x</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">
is replaced throughout the definition for </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">multiply</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">
with this value. Further, since the value for the parameter </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">x</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> is now specified, then this formal
parameter can be removed from the definition. We then effectively produce the
function:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">{ final int y ->
return 2 + y }<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">one
that takes a single numeric parameter and returns 2 times its value. This function
is the value bound to the identifier <b>twice</b>.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Since
a Groovy closure is an object and a Groovy closure can return a closure, then
currying can be achieved through another route. In Example 3.2 we have defined
a closure </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">add</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> which takes a single
parameter </span><b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">x</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> and returns a closure.
The returned closure is defined both in terms of its own parameter (y) as well
as </span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">x</span><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">,
sometimes described as a <i>free variable</i>
when used in this manner.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Example 3.2</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">: <i>Alternative currying</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // add:: Integer -> Integer ->
Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final add =
{ final int x -><o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> return { final int y -> x + y }<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // successor:: Integer -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final
successor = add(1)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
successor(5) == 6<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
successor(successor(5)) == 7<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">In
Example 3.2 the call add(1) delivers a closure that is bound to the <b>successor</b> identifier. In that closure
the free variable <b>x</b> has been fixed
as the value 1.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Interestingly
function <b>add</b> expects a single
parameter and delivers a function. That function also expects a single parameter
and delivers some result. As shown we are able to support currying without
using the <b>curry</b> method. It also
moves us to adopting the notion of functions only ever taking one parameter.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Why?
Well first we get currying for free. Second, it greatly enhances our capacity
to compose functions. Function composition in the previous blog expected them
to operate with only a single parameter.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Suppose
we want to develop a curried version of a binary function <b>f</b> which is <i>uncurried</i> and
of the type A * B -> C. This binary function <b>f</b> expects its parameters as a pair but its curried version will
apply them sequentially. We therefore have to form them into a pair before
applying <b>f</b> to them. The function <b>C</b> does exactly this:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // C:: (A * B -> C) -> A -> B
-> C<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final C = {
f -> { a -> { b -> f(a, b) }}}<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Again,
the signature reveals what is happening. Function <b>C</b> expects a function as its first parameter. That parameter
function has the signature A * B -> C, an uncurried binary function.
Function <b>C</b> returns the curried
function with the signature A -> B -> C, as required. We can use <b>C</b> where we need to transform an
uncurried binary function into its curried form.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;"> Example 3.3 introduces function <b>C</b> and its complementary function <b>U</b>. Using <b>U</b> we convert the curried <b>mul</b>
function into it uncurried equivalent, <b>mulU</b>.
Using <b>C</b> we transform the uncurried <b>mulU</b> function into its curried
equivalent, <b>mulC</b>.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Example 3.3</span></b><span style="font-family: 'Comic Sans MS'; font-size: 10pt;">: <i>Curried/uncurried transformation</i><o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // mul:: Integer -> Integer ->
Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final mul =
{ final int x -> { final int y -> x * y }}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // U:: (A -> B -> C) -> (A * B)
-> C<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final U = {
final f -> { final a, final b -> f(a)(b) }}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // mulU:: (Integer * Integer) -> Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final mulU
= U(mul)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
mul(3)(4) == 12<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
mulU(3, 4) == 12<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
U(mul)(3, 4) == 12<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // C:: (A * B -> C) -> A -> B
-> C<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final C = {
final f -> { final a -> { final b -> f(a, b) }}}<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;"> // mulC:: Integer -> Integer ->
Integer<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">final mulC
= C(mulU)<o:p></o:p></span></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-attachment: initial; background-clip: initial; background-color: #d9d9d9; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; margin-bottom: 0.0001pt; margin-left: 14.2pt; margin-right: 0cm; margin-top: 0cm; text-align: justify;">
<span style="font-family: Arial, sans-serif; font-size: 9pt;">assert
mulC(3)(4) == 12<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Various factory design patterns are used throughout
OO-land. The earlier examples showed currying as a mechanism for developing a
family of functions from a single definition. In effect currying is a form of <i>factory for functions</i>.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<span style="font-family: 'Comic Sans MS'; font-size: 10pt;">Many
of the emerging examples do not exploit Groovy meta-programming capabilities.
They also make ever greater demands on the types of quantities, including our
function parameter and return types. This work makes a strong case for a Groovy
static type checker.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: justify;">
<br /></div>Ken Barclayhttp://www.blogger.com/profile/04361889154891370742noreply@blogger.com0