Imran/Malic
04/20/2019, 8:28 AMImran/Malic
04/20/2019, 8:42 AMsimon.vergauwen
04/20/2019, 8:59 AMsimon.vergauwen
04/20/2019, 8:59 AMsimon.vergauwen
04/20/2019, 8:59 AMimport arrow.core.Tuple2
import arrow.data.StateT
import arrow.effects.ForIO
import <http://arrow.effects.IO|arrow.effects.IO>
import arrow.effects.extensions.io.applicative.applicative
import arrow.effects.extensions.io.monad.monad
object City
object Forecast
typealias Requests = Map<City, Forecast>
typealias StateReq<A> = StateT<ForIO, Requests, A>
fun fetchForecast(city: City, host: String, port: Int): StateReq<Forecast> =
TODO()
fun getForecastFromRequests(city: City): StateReq<Forecast?> = StateT(IO.applicative()) { reqs: Requests ->
IO { Tuple2(reqs, reqs[city]) }
}
fun getForecastFromDB(mForecast: Forecast?, host: String, port: Int): StateReq<Forecast> = StateT(IO.applicative()) { reqs: Requests ->
IO { Tuple2(reqs, mForecast!!) }
}
fun updateRequests(city: City, forecast: Forecast): StateReq<Unit> = StateT(IO.applicative()) { reqs: Requests ->
IO { Tuple2(reqs + (city to Forecast), Unit) }
}
simon.vergauwen
04/20/2019, 9:00 AMfx
is only enabled in a commutative way for state on the snapshot atm. cc/ @raulrajaImran/Malic
04/20/2019, 9:04 AMImran/Malic
04/20/2019, 9:05 AMImran/Malic
04/20/2019, 9:06 AMsimon.vergauwen
04/20/2019, 9:07 AMflatMap
anywaysimon.vergauwen
04/20/2019, 9:07 AMfun fetchForecast(city: City, host: String, port: Int): StateReq<Forecast> =
getForecastFromRequests(city).flatMap(IO.monad()) { mForecast ->
getForecastFromDB(mForecast, host, port).flatMap(IO.monad()) { forecast ->
updateRequests(city, forecast)
}
}
simon.vergauwen
04/20/2019, 9:07 AMStateT
works at leastsimon.vergauwen
04/20/2019, 9:07 AMImran/Malic
04/20/2019, 9:08 AMsimon.vergauwen
04/20/2019, 9:08 AMListK
fx has the same restriction atmImran/Malic
04/20/2019, 9:08 AMImran/Malic
04/20/2019, 9:08 AMpackage arrow.core.extensions.option.fx
@kotlin.jvm.JvmName public fun <A> fx(arg0: suspend arrow.typeclasses.MonadContinuation<arrow.core.ForOption, *>.() -> A): arrow.core.Option<A> { /* compiled code */ }
@kotlin.jvm.JvmName public fun monad(): arrow.typeclasses.Monad<arrow.core.ForOption> { /* compiled code */ }
public fun arrow.core.Option.Companion.fx(): arrow.core.extensions.OptionFx { /* compiled code */ }
simon.vergauwen
04/20/2019, 9:08 AMImran/Malic
04/20/2019, 9:11 AMImran/Malic
04/20/2019, 9:12 AMsimon.vergauwen
04/20/2019, 9:12 AMimport arrow.core.Tuple2
import arrow.data.StateT
import arrow.data.extensions.statet.fx.fx
import arrow.effects.ForIO
import <http://arrow.effects.IO|arrow.effects.IO>
import arrow.effects.extensions.io.applicative.applicative
import arrow.effects.extensions.io.monad.monad
import arrow.typeclasses.Monad
import arrow.unsafe
object City
object Forecast
typealias Requests = Map<City, Forecast>
typealias StateReq<A> = StateT<ForIO, Requests, A>
val IOMonad: Monad<ForIO> = IO.monad()
fun fetchForecast(city: City, host: String, port: Int): StateReq<Forecast> = unsafe {
fx<ForIO, Requests, Forecast>(IOMonad) {
val mForecast = getForecastFromRequests(city).bind()
val forecast = getForecastFromDB(mForecast, host, port).bind()
updateRequests(city, forecast).bind()
forecast
}
}
fun getForecastFromRequests(city: City): StateReq<Forecast?> = StateT(IO.applicative()) { reqs: Requests ->
IO { Tuple2(reqs, reqs[city]) }
}
fun getForecastFromDB(mForecast: Forecast?, host: String, port: Int): StateReq<Forecast> = StateT(IO.applicative()) { reqs: Requests ->
IO { Tuple2(reqs, mForecast!!) }
}
fun updateRequests(city: City, forecast: Forecast): StateReq<Unit> = StateT(IO.applicative()) { reqs: Requests ->
IO { Tuple2(reqs + (city to Forecast), Unit) }
}
simon.vergauwen
04/20/2019, 9:13 AMunsafe
atmsimon.vergauwen
04/20/2019, 9:13 AMI let you know, when I need your review 😉
simon.vergauwen
04/20/2019, 9:13 AMsimon.vergauwen
04/20/2019, 9:21 AMImran/Malic
04/22/2019, 7:30 AMval weather: (City, Tuple2<String, Int>) -> IO<Forcast> =
{ city: City, tuple: Tuple2<String, Int> ->
fx {
!effect { WeatherClient(tuple.a, tuple.b).forcast(city).getOrDefault { Forcast() } }
}
}
val hottestCity =
State<Requests, Temperature> { it toT (Request.hottest(it).b.temp) }
fun askCity() = fx {
!effect { putStrLn("What is the next city?") }
}
fun fetchForecast(city: City, host: String, port: Int): StateReq<Forcast> = unsafe {
fx(IO.monad()) {
val mForecast: StateReq<Forcast> = StateT(IO.applicative())
{ reqs: Requests ->
IO { reqs toT
reqs.getOrElse(city,
{ fx { !effect { weather(city, host toT port).unsafeRunSync()} }.unsafeRunSync() } // call to third-party
)
}
}
// still WIP
val forecast =
StateT(IO.applicative()) { reqs: Requests ->
IO { reqs toT mForecast.unsafeFetchWithIO(reqs) }
}
//updateRequests(city, forecast)
//forecast
}
}
fun <A> StateReq<A>.unsafeFetchWithIO(reqs: Requests) =
runA(IO.monad(), reqs).fix().unsafeRunSync()
Imran/Malic
04/22/2019, 7:31 AM