arrow-kt / arrow-core

Λrrow Core is part of Λrrow, a functional companion to Kotlin's Standard Library
http://arrow-kt.io
Other
81 stars 30 forks source link

["Request"] Add a `fold` function for nullable types #241

Open LordRaydenMK opened 4 years ago

LordRaydenMK commented 4 years ago

What version are you currently using?

0.11

What would you like to see?

When moving from Option to using nullable types, the fold function is missing so you end up doing:

?.let { ... } ?: run { ... }

We can add a function:

fun <A, B> A?.fold(ifNull: () -> B, ifPresent: (A) -> B): B =
    this?.let(ifPresent) ?: ifNull()

that would make this a bit easier to work with.

Source: https://github.com/arrow-kt/arrow-core/pull/239#discussion_r495479486 suggested by @pablisco

You can also see the pattern in the PR.

pablisco commented 4 years ago

If we mirror the current Option API for nullables it will make migration much easier as we can use ReplaceWith without any compilation errors after the replacement. Aditionally, having map, flatMap and such would be a nice companion to stdlib

raulraja commented 4 years ago

Can we make these inline?

pablisco commented 4 years ago

After more time than I would like to admit, I realised one problem... A? is contravariant of all Kinded types, so it adds ambiguity and, for obvious reasons, it cannot be resolved 🤦

Maybe if we call it foldNull? I'm uncertain if there will be inline classes in the future. This indicates that could be (maybe?) https://github.com/Kotlin/KEEP/blob/master/proposals/inline-classes.md#inline-classes-over-nullable-reference-types

That would be the ideal solution, in reality, so we can avoid polluting the global scope with extension functions like these.

nomisRev commented 3 years ago

Yes, we currently also have this issue with mapN defined in Nullable.kt it's conflicing with mapN for List and possibly other top-level methods such as mapN, tupledN we might want to add for other types. I don't think it makes sense to add such extensions on A?, but arity builders functions like mapN which require a lot of boilerplate I do think it makes sense.

this?.let(ifPresent) ?: ifNull() is more Kotlin idiomatic than this.fold(ifPresent, ifNull).