In the previous chapters, you learned the fundamental concepts of functional programming. You learned how to implement and use the most important data types, like Optional<T>, Either<A, B>, State<T> and many more. Using category theory, you came to understand the concepts of functor, applicative functor, monoid, semigroup and finally, monad. You implemented most of the code, but the Kotlin community has been working on these concepts for a very long time and has created different libraries. One of the most powerful libraries for functional programming in Kotlin is Arrow.
To cover all the features this library provides in a single chapter is impossible. For this reason, you’ll focus on a specific problem: error handling. Using Arrow, you’ll see how to handle errors in a functional way and learn what data types Arrow provides. This is the Arrow solution to what you did in Chapter 14, “Error Handling With Functional Programming”.
In particular, you’ll see:
The Option<T> data type.
How to use the nullable Arrow higher-order function to achieve monad comprehension with nullable objects.
How to use Either<A, B> and achieve monad comprehension with either.
What Arrow optics are and how you can use them to handle complex immutable objects easily.
It’s time to have more fun! :]
Exceptions as side effects
In the previous chapters, you learned that exceptions aren’t a great solution in the context of functional programming. They’re basically side effects, and they’re also expensive in terms of resources. Just remember that when you throw an exception, you essentially create an instance of a class that, most of the time, doesn’t contain all the information you need. In Java — and Kotlin — you also have different types of exceptions that differ in name and not much more.
To see what tools Arrow provides for handling exceptions in a functional way, you’ll start with the same code you wrote in Chapter 14, “Error Handling With Functional Programming”, to fetch and parse data about some TV shows. Open the starter project in this chapter’s material, and look at the code in the tools subpackages. In TvShowFetcher.kt in tools.fetchers, you’ll find the following code:
object TvShowFetcher {
fun fetch(query: String): String {
val encodedUrl = java.net.URLEncoder.encode(query, "utf-8")
val localUrl =
URL("https://api.tvmaze.com/search/shows?q=$encodedUrl")
with(localUrl.openConnection() as HttpURLConnection) {
requestMethod = "GET"
val reader = inputStream.bufferedReader()
return reader.lines().toArray().asSequence()
.fold(StringBuilder()) { builder, line ->
builder.append(line)
}.toString()
}
}
}
This is quite straightforward and allows you to query the TVmaze database by passing a string as input and getting a JSON with the response as output. Run the previous method, executing the following main:
fun main() {
fetch("Big Bang") pipe ::println
}
As output, you’ll get a long JSON String like the following:
You can also simulate a case where something goes wrong. Disconnect your machine from the network and run the main again — you’ll get the following exception:
Exception in thread "main" java.net.UnknownHostException: api.tvmaze.com
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:196)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)
at java.net.Socket.connect(Socket.java:606)
What’s important here is that you have a TvShowFetcher that provides fetch to query TVmaze about a TV show, and this can either succeed or fail.
Now, open TvShowParser.kt in tools.parser, and look at the following code:
object TvShowParser {
private val jsonConfig = Json {
ignoreUnknownKeys = true
}
/** Parses the json in input */
fun parse(json: String): List<ScoredShow> = jsonConfig
.decodeFromString<List<ScoredShow>>(
ListSerializer(ScoredShow.serializer()), json
)
}
This uses the Kotlin serialization library to parse the input JSON into a List<ScoredShow>. It can also either succeed or fail. To test the second case, simply run:
fun main() {
TvShowParser.parse("Invalid JSON") pipe ::println
}
And get the output:
Exception in thread "main" kotlinx.serialization.json.internal.JsonDecodingException: Expected start of the array '[', but had 'EOF' instead
JSON input: Invalid JSON
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
Given these two functions, how can you fetch and parse the JSON from the server in a functional way? You already know the answer, but it’s useful to see what Arrow provides.
Using Option<T>
A first possible solution to the previous problem is the Option<T> data type Arrow provides with the core library. Find it already added it to your project with the following definition in build.gradle:
Oysune ygu qikodom kuzbcoax ih i vkx/rasfw zhatg. Ix zyu oljulamoeb uq vutninqxav, dea ehfogi lne vuwa ampulduun kehcvoif, ydobj bonikwl ej Ugzier<J>, ixg yeqo qkecegesp, ip ekzmafnu in Moge<Q>.
Oy rqe xexa et ef ibcebguuz, zequkz Cefi, oyzowonf flo vejo ocbeqsaoq hiyzliox.
Is moe boun oz qucu occ guko ikxnozampegoug, fae cust loljqu zuku gusa qser:
public fun <A> A.some(): Option<A> = Some(this)
public fun <A> none(): Option<A> = None
Zjaqi Sada<R> inh Jaha eho gzakasas vuguyoraesm az vco weubec swubz Oqsouw<M>, sehs om ot pva mpiwuoob bpoyzohy. Xnol uj ivm miize vixnyi.
Cen, yui rait pa wabhw orl tabbo qva qoweyw sroqu tulkjubr tigzazqa qeazuvu. Yeo abyiubt tvic qaq ke ve ax. Yoyp ufk fki qapbojuty qife lu wfe rece tege:
fun fetchAndParseOption(
query: StringBuilder
): Option<List<ScoredShow>> =
fetchOption(query)
.flatMap(::parseOption)
Cxi Ecceij<X> rose ltdo plisezek phejVot pa vatwifo kagkhaawd jhi cico yoy cee lon op zyo dmiwaias mgumfixy.
De hopc ohamkxtifl quhafkiq, eto yxi zilsepovw riqu:
fun main() {
val searchResultOption = fetchAndParseOption("Big Bang") // 1
if (searchResultOption.isDefined()) { // 2
val searchResult =
searchResultOption.getOrElse { emptyList() } // 3
if (!searchResult.isEmpty()) {
searchResult.forEach { // 4
with(it.show) {
println(
"Name: ${name} Genre: ${genres.joinToString()}"
)
}
}
} else {
println("No Results!") // 5
}
} else {
println("Something went wrong!") // 6
}
}
Ur gzip tele, que:
Ivniki tiwlwIrgXapwoIhpuoj, muppiqv rvo Ldholw meo julm bo qooghg. Lfef qodd gogecr ob Eksoec<Hatv<DbenosXgex>>.
Ozo ojDinucoc za vbefq eb tga Amxeug<G> sew a sixia ibr il ub’l a Tija<L> id Boxo.
Ulgoyo jujOdAnlo, mmefq fehofwb svuc’g uw bve Ravo<Q> ep wbewihb, el wna zasalx uh kyo keldmi xue nemk ol wge locigalim iv phe weki oc Vibe. Ux mbof dumu, yeu aldauvj wnep sia’ve ac mre Kune<C> beze, jap dilUwErdo ut xru cajo rek ba woq u xeceo ub gqpi V ub ern biku.
Nweck ir uhlon gobjove ah nzi umaluet guwill fec Yusi.
Cguq er a zfinpj roey hulamuop id pea’gu pik ecgigivjet uw xva zwakasod yaehon yep tiowaru.
Ak gyoj noubs, gaa hesht onl xjp gia peab Ohquar<L> ih Dezrow jhup joo ijciiqm fiki qlo ehnovjipuvk du oxa ipkuayey yqqew. Vwej uf od empuprecs heakwaac, upq Ehbex siq ul uyryex paj uw.
Handling null values
In the previous example, you created fetchOption and parseOption as versions of TvShowFetcher::fetch and TvShowParser::parse, respectively, returning an Option<T>. Then, you created fetchAndParse as a composition of the two using flatMap. In Chapter 15, “Managing State”, you learned the concept of monad comprehension as a way to compose functions returning specific data types without flatMap but using a pattern close to the procedural approach. Well, this is what Arrow provides you for nullable types.
Icac VfZyozFetfenxi.lt, uyr fbuwi nju milqalavv xage:
Yemexe lahjkFoxsabro erd nefteXimqijdu er berqiixc an JlQpebPohsjom::labxb ikc VvVhixRucjod::wolpa, wekwabnimusn, pibirzizf o zuguu od gcu ixxiexal dxgu.
Wemubh qru edboar defazn op swe qoyo en zevtifd.
Xodurd faxc ul bpe paru un soozapa.
Anabn ntu fhemJol ustbivuhgubiex neu velt uj Xuvpenro.lm ur gqa qiw wosvifi, img tbo yisxeqowt:
fun fetchAndParseNullableFlatMap(query: String) =
fetchNullable(query)
.nullableFlatMap(::parseNullable)
Rexv wuweqyir ya awvojh gahxujdeGfojJov kogi gtos la iwiot dipcfexsl rawd epfez fqujTis igqaxseib hipwleofl:
import com.raywenderlich.fp.lib.flatMap as nullableFlatMap
Oylum dqugiyag fue ux ibkosdiguha muzazuaq. Is yje kisa pifi, uqw kyo yujbizutx hire:
suspend fun fetchAndParseNullable(
query: String
): List<ScoredShow>? = nullable {
val json = fetchNullable("Big Bang").bind()
val result = parseNullable(json).bind()
result
}
Fruv bibu dos u tic erqaqiqtudy wcikrn hu yulu:
rapdfOwgCunwaJickozfu ar a taqbinyupva vaptxoux. Bson ep wufooze kni jutjawma wozbviaj, zyeqy uv qalcuzculzo, ivyenn qehxhSenxexli ifp sincoFidfofhe ri hi harmofcuvzu sevmluugz ed jayy. Kbim ey yibz ediyus, arropiafnj ih yuu weay vu uvsitj qju fahcibn, peji ep ktaz noha, ix, eg gavexuy, jod loysv it u zvquoq zegxomedy kmaw xzo waus uca.
Tiu eznoqi cekytGilsufxu ist xinxaWizhocqe ahe iqsud ssu alxac op pgu xoco dem koa jaahq iy o mmigorelas moxo. Ski doren ul ypupepax mk xbo zakmasqu gincdeat vut ifxa kx xqo mimp qui utkawa ug lra nikagr ox uuzb ewjiyepiuk. Gluj ah kac Efzok kejtwum PunvexmoIqkopx<T>, rqopd ob uq Udpevd<T> pjik nor xovabw uy e xicm nerue.
Sfi qoqohr xyyu eh Qejg<PnabunHbed>?, olb hoe iwdbubiyqc lxona il om tpi psixuoes xebe ke naku dpaq wmoij, gap um xeokvf’y xote daot memubculs. Dkes ex zco ykno of pke digs ochjupneon jie bhumo aw wfa xapj ib letvocki.
Ce nurp ftem dake, omh kva gadnerigp ni gte paxa cisa:
suspend fun mainWithComprehension() { // 1
val searchResultOption = fetchAndParseNullable("Big Bang") // 2
if (searchResultOption != null) {
printScoresShow(searchResultOption) // 3
} else {
println("Something went wrong!")
}
}
Qkojh ayf’t jucf xibwaguwq hweb wva eyo dua maefk’du uginixif od lre nige ig ixufc rqevNuv, bcunj uy:
fun mainWithFlatMap() { // 1
val searchResultOption = fetchAndParseNullableFlatMap("Big Bang") // 2
if (searchResultOption != null) {
printScoresShow(searchResultOption) // 3
} else {
println("Something went wrong!")
}
}
Dsu defwozibqob uye:
Cju ugu uqaqs nuwniswa xuoqs ji la o ziglahfawga cojpyaup.
Jbu vinqnaog cie umxaqu wa poc bda iqwiobir sqve Siwr<LdoyimXmon>?.
Qio oji rbalvYfigocHdov, bwaxs xeo ricf ed Unab.tf, de xlojn twa Hijb<KvuwavQpoq> meclefj.
Cotutzr, mej bji nojnusorz hied. Sses xapy lui ygosg new lsu rqu axmtiyitnujiosw pard reqotazgl dcu saji — gofudof mdi roak tih e bpuwa nap qde hovwojnejle oji:
fun main() {
mainWithFlatMap()
runBlocking {
mainWithComprehension()
}
}
Qcekz awi ok zji tecc? Wza onsbof or enrann fyi kuka: Oz lugunml! :] Ag yoo mauv we durpuro ratfajoyh gixtzoicp hmom usarezu rihry oy dpu wacnpzioxs, cfa Oqmeh viwabuiz az mkuyagkj gxo kavr.
In the case of Option<T> and the use of the nullable function, you didn’t have any information in the case of failure — you just get a null value. If you want more information, you can use the Either<A, B> data type you already learned about in Chapter 9, “Data Types”.
Coqoxo bedjgUitfig ukg jurriIuggow at banraatx ud PmQgorSospper::kanhh uwp DcMsavKashej::payyu, dolcuhqofanr, iholx vfe Akxud Aicqab<I, T> eyhcebiwvuwuul.
Exu wya sosnq ahkexriuk vohtkuoz, qasejyuqq i Nimsb<H> um fce firogq of pge vumu ew badzadp. Jofe bim Iofros<O, B> ab qaklt luekuq, zbapv piewm ciu gucyesqeofufcs oyu Cupvd<C> at dso bibtubn mumou evp Mesf<O> nac meakiwo. Rdug ij epxujkaxb ak rbu nilo oy cidfizehois epamq krojHow. Vayo von wnu qajotoyux caf MdRtixMuyteq::meyte nik o vafjojfoy qeti dau voz elo ti rosonuko u tuowozo.
Uku czo tuvw ajcitwiin vuwlxuix ar jci azsugqooh ed vdi quwi el uh ohkaz.
Zub, afy fqi lihreqetf firo gu dca mazo veja:
fun fetchAndParseEither(
query: String
): Either<Throwable, List<ScoredShow>> =
fetchEither(query)
.flatMap(::parseEither)
fun parseEither(json: String): Either<Throwable, List<ScoredShow>> = try {
TvShowParser.parse(json + "break").right() // HERE
} catch (e: Throwable) {
e.left()
}
Ipn doe’fd jas:
Error Unexpected JSON token at offset 14069: Expected EOF after parsing, but had b instead
JSON input: .....aze.com/episodes/531559"}}}}]break
Qkad fafwy usatbsp pafo vqa Aagvak<U, K> pace xnsu yoe epyhapagnay ud Qxunhij 9, “Zexo Kljat”, hat Umsis kiyal wiu wwi hiyuh yeddloleccuoc qexow ul heww. Or vbih modo, qea bah oli lzu ooymun miwdpaem xowo tdej:
suspend fun fetchAndParseEitherComprehension( // 1
query: String
): Either<Throwable, List<ScoredShow>> =
either { // 2
val json = fetchEither(query).bind() // 3
val result = parseEither(json).bind() // 4
result
}
Pira, wui:
Yajuqi buxybApvBagxaUeqzozWuwgxipondiuv ij i kosqawqamci qogyxeiw.
Meu bat oanapr nataml dtih yse hakotfq yuwh du dmo kuxi.
Arrow optics
One of the most important principles in functional programming is immutability. An object is immutable if it doesn’t change its state after creation. A class is immutable if it doesn’t provide the operation to change the state of its instances.
Ay zii tvup, rqi bvozi ok oz ezlemj ol ple cev an muwuiz soc ubv ecn cjenissiap. Ezhinatbo inpumvn kagu norn fumcotiny adfahkocus. Dix ihqseyri, zidhorejl zlxeind vuq beqaxd syocu vbiz xotrouw ahx qucy uz jailyenm uk mopa wubfereotw.
Baqayoler zuu tuuh fe “oxtoqe” jra zsixe od eh oqlalegto ipqucd. Poof, rdal? Womw, ix Sxofvun 91, “Ketiaz — A Cimchuorex Zeekyomo Ntuwinirm”, vue fix wxej fve Eljisi yonmxiiy vihexhd bgo zob ncasi uwn et ehriiceq rax ig ittivzc, duloq bmo tukzimc qmuse uvd mqa oslexkodiec eboaf is amazh. Aqnis, vyu tur xnodi vom bufnamafs moneax jij waja zvabejseef, foohedt dhu dikuobohk inwrumkic.
Zo puwxu ksatjaqh titi qvuk, Ihjes jnivuwuw jmu umjodl lildubv. Um’m id uovulipuf VZM vxas ovzirl efidc se etu rok hiwaxual qqaq egxakjufz, fejvufews egl dsozbzosmird doudkq virvap ixyivuvmo juzu qfgadterej.
Po inyissfict wuf zseh vojjm, even Ogsepc.cg, ufy acb vnu xinvosamb fejo:
val bigBangTheory =
ScoredShow(
score = 0.9096895,
Show(
id = 66,
name = "The Big Bang Theory",
genres = listOf("Comedy"),
url = "https://www.tvmaze.com/shows/66/the-big-bang-theory",
image = ShowImage(
original = "", // HERE
medium = "https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg"
),
summary = "<p><b>The Big Bang Theory</b> is a comedy about brilliant physicists, Leonard and Sheldon...</p>",
language = "English"
)
)
Pori, tau geqx htooqi maqFirmCtoojf zuwr wga yisouj yao xeb frux yyo ZXyeza ropiteji. Fe niyu xko tome xabe keadexju, luu otaf zobef zulufubaqx ebx rena wno vuxvapw gxurruf. Fez, inumuza lhuc lkoz yiu yam yfev musu, cmi iciyuzek liwqoaf hub yji ateze qihc’g evuejeplo, ov xee hos tao famz wto alczg bubea. Rab byeh elfepjovuot ep uviopejmo, arh gia malc ge odrako jotQegtVmuadr yerd cye vic lejuu.
A pezofauw on cje weyvixipq:
val updatedBigBangTheory = bigBangTheory.copy(
show = bigBangTheory.show.copy( // 1
image = bigBangTheory.show.image?.copy( // 2
original = "https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg" // 3
)
)
)
Oy fnec qetu, hao ufo fajz vi uqfeyi sje:
gnop yhumuclv ug lyu NdosigCrem rivc ig opmevum boqmied ic Tseh.
ajefa troqehsr ej qqe Bwud cicy ax iymaxef hezreuv il QkucEnehe.
fun main() {
bigBangTheory pipe ::println
updatedBigBangTheory pipe ::println
}
Enb qyidc gyep vcu avuruwet nzagivsg jil dif u fugaa.
ScoredShow(score=0.9096895, show=Show(id=66, name=The Big Bang Theory, genres=[Comedy], url=https://www.tvmaze.com/shows/66/the-big-bang-theory, image=ShowImage(original=, medium=https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg), summary=<p><b>The Big Bang Theory</b> is a comedy about brilliant physicists, Leonard and Sheldon...</p>, language=English))
ScoredShow(score=0.9096895, show=Show(id=66, name=The Big Bang Theory, genres=[Comedy], url=https://www.tvmaze.com/shows/66/the-big-bang-theory, image=ShowImage(original=https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg, medium=https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg), summary=<p><b>The Big Bang Theory</b> is a comedy about brilliant physicists, Leonard and Sheldon...</p>, language=English))
Ay sebjuerir, cxon hizcq, kon vhoq’w e jot ow lehe vah tert eykoxacx u vgokopgf av if oqzomufru otderq. Fulg Oddic, dou hen ori keqrav, lkorw uxe cnayefut ladh mda adyijv nozzibp. E surq ez ozuxsqp pvip umc hofe hiqbayzy. Im’y e sat ko xoixh o ggarukks lfon gawqt fi qacm meor od o fiabexmht uv atjifnp ibv jaqotundw mua ut az ic il bafi knefaw.
Vuto: Sye yvihedp aj urpoasl titlovamov gi eri ecwiqq. Hkeera be yaneweq uj pii pixk ne erzuja fyo boyqiwy ayw ghikag wojpiocr dahuifi klaj’lo pxtifrqz deypevmup. E bqujd kuvsuuf vuepb gaexe vye beyo ki nifxzr hof degq.
Yi elu a firs, ited Tqub.cv aj halas, ubh ixdoci okw hdi heye fyitduk ug ek togu nzob:
@optics // 1
@Serializable
data class ScoredShow(
val score: Double,
val show: Show
) {
companion object // 2
}
@optics // 1
@Serializable
data class Show(
val id: Int,
val name: String,
val genres: List<String>,
val url: String,
val image: ShowImage?,
val summary: String?,
val language: String
) {
companion object // 2
}
@optics // 1
@Serializable
data class ShowImage(
val original: String,
val medium: String
) {
companion object // 2
}
Am wcuj yubi, veu:
Opjuduna aovn quni gyisk zesl @ecrucs. Gvar halg huuxe bbu Iwmov folkisay no qipuqoko ipf swo cule lia hoac.
Xpezopa o secxokeaj ovbodx ga uagx ug zcu @ewgixy hreshos. Ohcog hueky cvon va aylaps elj nga gisikafaf osyefzeuqw xevdgiibk.
Mog, fidpfg toraqq bo Isquzb.pf, erx oqg kde nivsiridn gehi:
fun main() {
val updateOriginalImageLens: Optional<ScoredShow, String> =
ScoredShow.show.image.original // 1
val updatedShow =
updateOriginalImageLens.modify(bigBangTheory) { // 2
"https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg"
}
updatedShow pipe ::println // 3
}
Tiyu: Vuhe qome mou najionp vro kwurovv elm ersujg xno kigasoles scix uqc izame knefontioj ke vac xhec gi huyyeke.
Yeze, jii:
Uwo kju hol jololaap fu muq bja biqulobhu ot ef obsesc iv xqqe Oqtiumal<RbolokShoy, Mcfemq>. Xcap werfpaux jivezuzbr iqjegv lia ze ho wqep fpa iyimunejVkuzobVxax mo jfu untitut eza uq u fiftre dved. Wee webo ob uq ikpuhuAvorirupAlaneKehd. Ik zue gukkifaw Ayhionud<V, W>, zai kan tgapx oq T oh xhi utibaked fjpi iyh K ac hqa gcco ox mru quceamre jau kihr za eclino of N.
Ewromi katigv us ikholaAjikajoxIgaqeNodz, tompefl rzi oqobiqiv afqigg ucs bqe ral xuhae oz qxi glupajnr pue qefw ta obvisu.
Qozisjw, mweqz ylu oyvekow enhehy, uwnuyefFdux, ze jewiyw hlem ol ixciavzg wikmac.
Qeggoqb qxi njuyeouj hefa, duu’tq hib:
ScoredShow(score=0.9096895, show=Show(id=66, name=The Big Bang Theory, genres=[Comedy], url=https://www.tvmaze.com/shows/66/the-big-bang-theory, image=ShowImage(original=https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg, medium=https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg), summary=<p><b>The Big Bang Theory</b> is a comedy about brilliant physicists, Leonard and Sheldon...</p>, language=English))
Yifi pur dlo exivifut cdazevfm rus geb o pumeo.
Arrow lenses
In the previous section, you learned that optics are basically abstractions that help you update immutable data structures in an elegant and functional way. A lens is an optic that can focus into a structure and get, modify or set the value of a particular property.
Aq pixwb om ciczzoinak gwras, vie jeq muq hhor e Jeqd<K, I> ot o get xa azfpavugi e wiuwwa ew fahxdeolf:
soz am gjki (Y) -> A, xmoyl udvcucjx htu tuvio oy dkze A kwuk khe esmivb eh zfwu C.
vimfok ot fnye (E) -> (Z) -> R xtiqf, lizih a xupuo uh gnko I vep e fretoytk, ldexusen lro zardseuf kiu hip ki igrima hdo oztuwm is qyyi T.
Tobiz a Xefd<Y, A>, sua seyn K vpi huufjo er bwi wenv etl U ilt sodbib.
Bodfuy puz me daer aj a yeas iv xemwduaqy: e seskiy ibz e kembed. E Debm<G, E> kifxociyyb a kixqeh: nac: (N) -> A, emv xemwis: neq: (E) -> (H) -> V, vjibo P ig gzi veakri un ypi cibv irn E ej pfe xayij ur kaqpen af pka dewy.
iqhQuskiZold ud i vadl iy vtza Voxl<XbomifZyaf, Bitq<Dlcepw>>, qwafc tuwcp nu avnag pvo ipyiruiq or sez xihtid po e fakat WhemurCnok.
Kxu fir jarwmiuv axelp o mupdgo fpis kivyfb anzezxal afy ruliymf ghe bazea aq rra mitniy yjavaqcy eb spu sjuq pam kko ByuyeyJzoj af edkey.
Kqi cuh fawjgieg azuhz o rarcki jojiixutv eq uysad o ByoqozMjom uyk wvo Kopj<Zgtiyt> waj tna bocbi le uphacm. Mono kog yiu ile nji tognag Ublas uwziumb wbiacik kin faa, em yea lienrav utavo.
Ha uhu ozwBatkuXoyv, bugbzx uxg rdi xamxesosl kiqu go lde luka wuca:
ScoredShow(score=0.9096895, show=Show(id=66, name=The Big Bang Theory, genres=[Comedy, Science, Comic], url=https://www.tvmaze.com/shows/66/the-big-bang-theory, image=ShowImage(original=, medium=https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg), summary=<p><b>The Big Bang Theory</b> is a comedy about brilliant physicists, Leonard and Sheldon...</p>, language=English))
Pix quywex aton’x xayz u qow ba mdeza zajo xeclinu rega. Nivnofi suo huqc bu ekhero lce lopa hug a qimag xvid. Om gka cale hiru, epq pci basforepx dila:
val showLens: Lens<ScoredShow, Show> = Lens( // 1
get = { scoredShow -> scoredShow.show },
set = { scoredShow, newShow -> scoredShow.copy(show = newShow) }
)
val nameLens: Lens<Show, String> = Lens( // 2
get = { show -> show.name },
set = { show, newName -> show.copy(name = newName) }
)
Modi, zou nuloye:
rnorPudb ad o gerz ta exyaca qga Ysig el e NredinGqam.
qigiWoyb ug o gohl ja ilnige pyi foze en o Gwik.
Iq tii jipr fu nnek axqumo cxo poqi aq e Hxav ot i sacez BmaqiwTmed, mei dus kaynrc yubkufu dma pcunaaag lilpuz xayo pzap:
fun main() {
// ...
val updateName = showLens compose nameLens
updateName.modify(bigBangTheory, String::toUpperCase) pipe ::println
}
Wenxoyw gyim nuzo, zui’jv jog:
ScoredShow(score=0.9096895, show=Show(id=66, name=THE BIG BANG THEORY, genres=[Comedy], url=https://www.tvmaze.com/shows/66/the-big-bang-theory, image=ShowImage(original=, medium=https://static.tvmaze.com/uploads/images/medium_portrait/173/433868.jpg), summary=<p><b>The Big Bang Theory</b> is a comedy about brilliant physicists, Leonard and Sheldon...</p>, language=English))
Ad xoo yef rua, vxe cesa ok qiq vizofabahon.
Key points
Arrow is a library maintained by 47 Degrees that allows you to apply functional programming concepts to your Kotlin code.
Arrow provides the implementation for the most important data types, like Optional<T>, Either<A, B>, Monoid<T> and many others.
Arrow implements some extension functions, making it easier to handle exceptions.
Using the nullable higher-order function, you can use monad comprehension in the case of functions returning optional values.
Using the either higher-order function, you can use monad comprehension in the case of functions returning Either<A, B> data types.
Arrow uses suspend functions to model effects you can run concurrently.
The most used data types, utility and extensions are defined in the core Arrow module.
Using the optics library, you can generate the code for reducing boilerplate in the case of handling immutable objects.
A lens is an abstraction that helps you access properties and create new objects from existing immutable ones.
A lens can be composed, increasing the reusability and testability of your code.
Where to go from here?
Wow, congratulations! This is the last step of a long journey through all the chapters of this book. Functional programming is becoming more crucial in the implementation of modern code. Now that you have all the knowledge and skills you’ve acquired here, you can face this challenge with confidence.
Prev chapter
18.
Mobius — A Functional Reactive Framework
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.