Anyone using Arrow on Android? How you use it? Ple...
# arrow
k
Anyone using Arrow on Android? How you use it? Please share your experience
t
Sure, using it basically in every project. Backend, Android, multiplatform stuff. On android we mainly use optics for state modifications, monad comprehensions (bind) in side effects and of course fx for async stuff.
😍 1
Oh yeah and refined types for domain modelling. Even though it's deprecated (looking forward to arrow-analysis 🙂 )
😍 1
k
@than_ Do you have any code sample, blog posts about usage in Android
t
not really. You can check 47deg.com but I'm not sure. Arrow is not a framework. It's set of tools and is really platform/architecture agnostic. So no tight integration with Android. No opinionated way to solve stuff. I believe it'd be more beneficial to search for "what's a functional approach to problem x?" and then "do arrow have tools for that?". this channel is really (and I mean REALLY) helpful with that.
I'd start with pure functions. Everything else will kinda snowball. Oh how do I solve error cases when I can't throw? ADTs and monads. Does Arrow have something in this area? It does, sweet! Ok now how do I handle state changes without mutability/impurity. Oh there is an MVI architecture. Boy does it suck to work with nested immutable data. Does Arrow have something for that. Yep optics! And so on and so on...
👍 1
☝️ 1
k
I know it is agnostic, I wanted to see how you use it in Android (ie : code examples)
j
The cool thing I've found about getting into FP via Arrow, is that it's like asking for a banana and getting a banana, and a gorilla holding the banana, and the tree holding the gorilla, and the forest holding the tree... You never need to see the forest up-front. In this analogy, the forest would be an example FP Android app. Eventually you'll be led there, naturally, step-by-step, by the sorts of problems you're faced with. This shouldn't be scary, because at each stage you're not forced to take the next step - you can always switch to the 00/imperative-programming you're familiar with when you run up against the limit of your FP knowledge. But what you'll find, over time, is that it's actually easier (and a lot more fun!) to level up in FP than to resort to OO/imperative. I started my journey just by introducing the
Either
data type so that I no longer threw exceptions, but instead modeled all possible function results as types. Then I tried introducing immutability into my app model. And so on... Hope that helps.
👍 2
l
I also started with using
Either
as the wrapper for my API calls made with Retrofit. I wrote a custom Retrofit
CallAdapter
to be able to define my API like this:
Copy code
data class User(val name: String)

interface MyService {

  @GET("/user/me")
  suspend fun user(): Either<CallError, User>
}
This way I can
flatMap
multiple API calls (or even better, put them into an
either
block and use the
bind
syntax). There is an open PR to include my Retrofit adapter into Arrow (there are already other adapters, but they still throw exceptions when there is no network, timeout or malformed JSON): https://github.com/arrow-kt/arrow/pull/2621
👍 3
k
@than_ @julian @Lukasz Kalnik Any comments on APK size increase after adding Arrow? How is the performance impact when using immutable data structures? (this is important specially on mobile)
t
When using r8 increased apk size is not a problem. Regarding immutable data structures. Do you perform thousands mutations per second? If so it could be a problem. There is an overhead of creating a new object for every "mutation" (except for collections 😕 ). But on the other hand detection whether object changed becomes trivial and thus significantly faster. So you can see actually performance increase. It really depends on your use case.
l
Immutable data structures make your code safer. Most mobile applications don't deal with such amounts of data that performance penalty because of using
copy()
on immutable data under the hood is a problem. If your app does have to perform lots of data operations that performance starts being important it's worth considering moving this logic to a backend. Anyway in my case the sole benefit of not having bugs in my code because of data being immutable is a much bigger benefit than any performance penalty (which in practice I didn't observe anyway). My app is basically a REST client with some UI logic, like most typical mobile apps nowadays.
👆 1
Maybe it would help if you would describe what app you are trying to use Arrow in and then we can recommend some use cases?
k
Regarding immutable data structures. Do you perform thousands mutations per second?
No, but AFIAK immutable data structures have memory overhead,
There is an overhead of creating a new object for every "mutation" (except for collections 😕 ).
@than_ I thought immutability is achieved through structural sharing
But on the other hand detection whether object changed becomes trivial and thus significantly faster. So you can see actually performance increase.
Can you please explain this?
@Lukasz Kalnik In my case I have to store data locally (SQLite) until user goes online.
l
Can you just try it out and test if you really experience performance/memory penalties with immutable data structures? From my experience people greatly overestimate the performance/memory impact on their apps.
t
I thought immutability is achieved through structural sharing
It is but you have to (by definition) create new instance of object for every change. That's the overhead. The unchanged content gets shared. Unfortunately collections don't perform structural sharing. But you can use kotlinx.immutable.collections for that.
But on the other hand detection whether object changed becomes trivial and thus significantly faster. So you can see actually performance increase.
Since every change creates new instance you can just check for referential equality.
From my experience people greatly overestimate the performance/memory impact on their apps.
^that. I've ever had only a single performance issue with immutability and that itself was a workaround to integrate with suboptimally designed 3rd party lib. Do we use mutability to gain a perf increase on some operations on collections? Yes. But from the callsite you won't know that because the mutability is contained.
l
Exactly, it's 2022. Our mobile apps run on 8 cores @ 2 GHz with 4 GB of RAM. Copying a 100-byte object doesn't really take that long. Also having 200 bytes in your RAM won't eat up your 4 GB. It's not like in the 8-bit era, where you had to squeeze every little optimization out of your code. BTW, computing the beautiful UI animations usually takes much more RAM/CPU cycles than the business logic of the app.
1
t
Yep. And that's actually one place where you can see performance increase when using immutable data structures. It's very fast to check what part of your UI needs to be rerendered.
👍 1
Anyway I'd worry more about correctness of the implementation. UI slugishness is less of a problem these days than app crashes/weird behavior. Users IMO don't care about slightly increased memory use. They do care if their app crashes though 😄
👆 1
r
We use
Either
heavily in prod (Android development). That makes all error handling to be in one place - a layer which holds state.
147 Views