Last active
March 22, 2021 11:53
-
-
Save timrijckaert/fbe90cf9b3d3f4c75116a06217da6cdb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.sample | |
import arrow.core.Either | |
import arrow.core.NonEmptyList | |
import arrow.core.computations.either | |
import arrow.core.flatMap | |
import arrow.core.nonEmptyListOf | |
import arrow.core.right | |
import arrow.core.traverseEither | |
import arrow.core.zip | |
import arrow.fx.coroutines.raceN | |
public data class NewsItem(val id: String) | |
public data class Detail(val id: String, val content: String) | |
public object Failure | |
public class Db | |
public class Nw | |
//<editor-fold desc="Singleton"> | |
public class AppModule(public val retrofit: Db, public val db: Nw) | |
public val appModule: AppModule = AppModule(Db(), Nw()) | |
//</editor-fold> | |
//<editor-fold desc="News List"> | |
public interface NewsRepository { | |
public suspend fun headlines(): Either<Failure, NonEmptyList<NewsItem>> | |
} | |
public class NewsRepositoryImpl(private val newsDataSource: NewsDataSource) : NewsRepository { | |
override suspend fun headlines(): Either<Failure, NonEmptyList<NewsItem>> = | |
newsDataSource.fetchNwHeadlines().zip(newsDataSource.fetchDbHeadlines()) { nw, db -> nw + db } | |
} | |
public interface HttpNewsDataSource { | |
public suspend fun fetchNwHeadlines(): Either<Failure, NonEmptyList<NewsItem>> | |
} | |
public interface DbNewsDataSource { | |
public suspend fun fetchDbHeadlines(): Either<Failure, NonEmptyList<NewsItem>> | |
} | |
public interface NewsDataSource : HttpNewsDataSource, DbNewsDataSource | |
public class NewsDataSourceImpl( | |
private val retroFit: Db, | |
private val db: Nw | |
) : NewsDataSource { | |
override suspend fun fetchNwHeadlines(): Either<Failure, NonEmptyList<NewsItem>> = | |
nonEmptyListOf( | |
NewsItem("1"), | |
NewsItem("2"), | |
NewsItem("3"), | |
).right() | |
override suspend fun fetchDbHeadlines(): Either<Failure, NonEmptyList<NewsItem>> = | |
nonEmptyListOf( | |
NewsItem("4"), | |
NewsItem("5"), | |
NewsItem("6"), | |
).right() | |
} | |
public interface ListModule { | |
public val newsRepository: NewsRepository | |
} | |
public suspend fun ListModule.headlines(): Either<Failure, NonEmptyList<NewsItem>> = newsRepository.headlines() | |
public fun newsListModule(appModule: AppModule): ListModule = | |
object : ListModule { | |
override val newsRepository: NewsRepository | |
get() = NewsRepositoryImpl(NewsDataSourceImpl(appModule.retrofit, appModule.db)) | |
} | |
//</editor-fold> | |
//<editor-fold desc="Detail"> | |
public interface DetailRepository { | |
public suspend fun detail(newsItem: NewsItem): Either<Failure, Detail> | |
} | |
public class DetailRepositoryImpl(private val detailDataSource: DetailDataSource) : DetailRepository { | |
override suspend fun detail(newsItem: NewsItem): Either<Failure, Detail> = | |
either { | |
raceN( | |
{ detailDataSource.fetchNwDetail(newsItem).bind() }, | |
{ detailDataSource.fetchDbDetail(newsItem).bind() } | |
).mapLeft { Failure }.bind() | |
} | |
} | |
public interface HttpDetailDataSource { | |
public suspend fun fetchNwDetail(newsItem: NewsItem): Either<Failure, Detail> | |
} | |
public interface DbDetailDataSource { | |
public suspend fun fetchDbDetail(newsItem: NewsItem): Either<Failure, Detail> | |
} | |
public interface DetailDataSource : HttpDetailDataSource, DbDetailDataSource | |
public class DetailDataSourceImpl(private val retrofit: Db, private val db: Nw) : DetailDataSource { | |
override suspend fun fetchNwDetail(newsItem: NewsItem): Either<Failure, Detail> = | |
Detail(newsItem.id, "Nw: Content of $newsItem").right() | |
override suspend fun fetchDbDetail(newsItem: NewsItem): Either<Failure, Detail> = | |
Detail(newsItem.id, "Db: Content of $newsItem").right() | |
} | |
public interface DetailModule { | |
public val detailRepository: DetailRepository | |
} | |
public suspend fun DetailModule.detail(newsItem: NewsItem): Either<Failure, Detail> = detailRepository.detail(newsItem) | |
public fun detailModule(appModule: AppModule): DetailModule = | |
object : DetailModule { | |
override val detailRepository: DetailRepository = | |
DetailRepositoryImpl(DetailDataSourceImpl(appModule.retrofit, appModule.db)) | |
} | |
//</editor-fold> | |
public suspend fun main() { | |
val newsList = newsListModule(appModule) | |
val detailModule = detailModule(appModule) | |
val detailPages = | |
newsList.headlines() | |
.flatMap { | |
it.traverseEither { newsItem -> detailModule.detail(newsItem) } | |
} | |
println(detailPages) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment