Arrow contains an integration module for Retrofit so you can use any synchronous or asynchronous datatype of your choice, like ObservableK or IO.

Using Call directly with extensions functions

It is possible to use extension functions for Retrofit’s Call so the code for the definition of the endpoints doesn’t have to change.

val call : Call<Response<String>>
call.runAsync(IO.async()) // Kind<ForIO, Response<String>>
    .fix() // IO<Response<String>> 		    
val call : Call<Response<String>>
call.runSyncDeferred(IO.monadDefer()) // Kind<ForIO, Response<String>>
    .fix() // IO<Response<String>> 		    
val call : Call<Response<String>>
call.runSyncCatch(IO.monadError()) // Kind<ForIO, Response<String>>
    .fix() // IO<Response<String>> 		    

Using the wrapper CallK

Use CallKindAdapterFactory.create() to register the Arrow adapter with Retrofit. Afterwards, you can start defining your endpoints using CallK as the return type:

interface ApiClientTest {

  fun testCallK(): CallK<ResponseMock>

  fun testCallKResponse(): CallK<ResponseMock>

  fun testIOResponsePost(): CallK<Unit>


You can use CallK to have Async, MonadDefer and MonadError instances as your data wrapper.

Using CallK with IO

  .testCallK() // CallK
  .async(IO.async()) // Kind<ForIO, Response<ResponseMock>>
  .fix() // IO<Response<ResponseMock>>

Using CallK with ObservableK

  .testCallK() // CallK
  .async(ObservableK.async()) // Kind<ForObservableK, Response<ResponseMock>>
  .fix() // ObservableK<Response<ResponseMock>>

Handling Response with Arrow

Arrow provides the extension function unwrapBody() for Response<A> to handle it using ApplicativeError<F, Throwable>. It wraps any failed response into an HttpException, and a missing body with IllegalStateException.

val ioResponse: IO<Response<ResponseMock>>
  .unsafeRunSync() //Response<ResponseMock>
  .unwrapBody(Either.applicativeError()) // Either<Throwable, ResponseMock>
  .fold({ throwable ->
    // Oops!
  }, {
    // Handle information

Do you like Arrow?

Arrow Org