kyleg
03/20/2020, 3:32 PMRef<ForIO, MyClass>
and a StateT<ForIO, MyClass, Unit>
, what is the best way to make these two work together (using the StateT
to update the value wrapped in Ref
?) I have to unpack the Ref
, pass it into the StateT
, and use the result to update the Ref
. I’m not sure how to do that without
myRef.update { oldState ->
val (newState, _) = myStateT.runM(IO.monad(), oldState).unsafeRunSync()
newState
}
but I know the unsafeRunSync
is the stinkiest code smell there ever was.raulraja
03/20/2020, 5:06 PMraulraja
03/20/2020, 5:07 PMraulraja
03/20/2020, 5:08 PMkyleg
03/20/2020, 6:09 PMsimon.vergauwen
03/20/2020, 6:10 PMState
for?simon.vergauwen
03/20/2020, 6:14 PMRef
will protect you from concurrent reading and writing like AtomicReference
does.
It’s however not safe to perform effects while updating
a Ref
which is why you require unsafeRunSync
theresimon.vergauwen
03/20/2020, 6:14 PMkyleg
03/20/2020, 6:16 PMdata class CarDetailViewState(val car: Option<CarEntity> = None)
class CarDetailViewModel(private val carDao: CarDao): ViewModel() {
private val viewStateRef = Ref(IO.monadDefer(), CarDetailViewState()).fix()
val carDetailFetcher = getCarDetail(carDao)
fun setCar(id: Int) = IO.fx {
val car = carDetailFetcher.run(IO.monad()).bind()
val (newState, _) = setCar(car).runM(IO.monad(), state).bind()
viewStateRef.bind().updateAndGet {
newState
}
set(car).runM(IO.monad()).flatMap {
}
}
fun setId(id: Int): IO<CarDetailViewState> {
return getCarDetail(carDao).run(id).fix().flatMap { entity ->
viewStateRef.flatMap { ref ->
ref.updateAndGet { oldState ->
oldState.copy(car= Some(entity))
}
}
}
}
}
fun setCar(car: CarEntity) = State<CarDetailViewState, Unit> {
it.copy(car=Some(car)) toT Unit
}
fun set(car: CarEntity) = StateT<ForIO, Ref<ForIO, CarDetailViewState>, Unit>(IO.monad()) { ref ->
IO.fx {
ref.getAndUpdate {
it.copy(car=Some(car))
} toT Unit
}
}
fun getCarDetail(carDao: CarDao) = ReaderT<ForIO, Int, CarEntity> { carId ->
IO.effect { Option.fromNullable(carDao.get(carId)) }
}
Couple drafts of same approach still in there, trying to work through concepts.kyleg
03/20/2020, 6:19 PMset(car: CarEntity)
has type inference failures right now because it’s incomplete. CarDetailViewModel::setCar
currently is referencing non-existent state
variable, second half is totally unfinished and based off at a recommendation Paco provided here so farkyleg
03/20/2020, 6:19 PMsimon.vergauwen
03/20/2020, 6:21 PMRef
and State
here.
@Jorge Castillo has a solution for Android using ViewModels, and we’re going to add them to the Arrow documentation very soon. We’re currently in the process of releasing.kyleg
03/20/2020, 6:23 PMRef
at all. But I ran into concurrency issues because userclicks, typing, etc. trigger state changes and I can’t serialize them.
Someone here (but not an Arrow maintainer or name I recognize) was very enthusiastic about me using Ref
for this reason. This is my first attempt at using Ref, so I’m 100% sure I don’t grok it 🙂kyleg
03/20/2020, 6:24 PMsimon.vergauwen
03/20/2020, 6:24 PMRef
is like AtomicRef
, so it doesn’t allow you to run IO
inside updates.
update
and modify
can potentially run multiple times in case the `update`/`modify` wasn’t valid. (It uses compareAndSet
in a loop until it returns true
). So you’re risking running the effect multiple times.simon.vergauwen
03/20/2020, 6:26 PMQueue
(or MVar
(functional mutable var, or single value queue).
That would allow you to send multiple events and receive multiple events.simon.vergauwen
03/20/2020, 6:27 PMsimon.vergauwen
03/20/2020, 6:27 PMkyleg
03/20/2020, 7:34 PMRef
was an Arrow name for the concept of MVar
, which I’d seen around on Haskell or Scalaz/Cats forums.
If you don’t have time to look at the snippet, don’t worry about it. It’s not mission critical; it’s me trying to learn, and I hate to have people spend time helping me with stuff that doesn’t even matter in the grand scheme of things, especially with everything going haywire in the world at the moment!