Last active
October 30, 2021 16:30
-
-
Save raulraja/97e2d5bf60e9d96680cf1fddcc90ee67 to your computer and use it in GitHub Desktop.
Simple Kotlin DI
This file contains 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.fortyseven.fptraining | |
import arrow.core.Either | |
import arrow.core.right | |
import arrow.effects.IO | |
import arrow.effects.extensions.io.fx.fx | |
data class Account(val balance: Int) | |
data class AccountEntity(val balance: Int) | |
/** User algebras **/ | |
interface UI { | |
fun present(): IO<Unit> | |
} | |
interface Domain { | |
fun getProcessedAccount(): IO<Account> | |
} | |
interface Data { | |
fun fetchAccount(): IO<AccountEntity> | |
} | |
/** interpreters */ | |
object InMemoryData : Data { | |
fun retrofit(callback: (Either<Throwable, AccountEntity>) -> Unit): Unit = | |
callback(AccountEntity(100).right()) | |
override fun fetchAccount(): IO<AccountEntity> = | |
IO.async { _, callback -> | |
retrofit(callback) | |
} | |
} | |
class DefaultDomain(val data: Data) : Domain { | |
override fun getProcessedAccount(): IO<Account> = | |
data.fetchAccount().map { Account(it.balance) } | |
} | |
class DefaultUI(val domain: Domain) : UI { | |
override fun present(): IO<Unit> = | |
fx { | |
val account = domain.getProcessedAccount().bind() | |
!effect { println(account) } | |
} | |
} | |
class Module( | |
data: Data = InMemoryData, | |
domain: Domain = DefaultDomain(data), | |
val ui: UI = DefaultUI(domain) | |
) { | |
companion object { | |
val defaultInstance = Module() | |
} | |
} | |
fun main() { | |
Module.defaultInstance.ui.present().unsafeRunSync() | |
} |
This file contains 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.fortyseven.fptraining | |
import arrow.core.Either | |
import arrow.core.right | |
import arrow.effects.IO | |
import arrow.effects.extensions.io.fx.fx | |
data class Account(val balance: Int) | |
data class AccountEntity(val balance: Int) | |
interface Data { | |
fun fetchAccount(): IO<AccountEntity> | |
} | |
class InMemoryData: Data { | |
fun retrofit(callback: (Either<Throwable, AccountEntity>) -> Unit): Unit = | |
callback(AccountEntity(100).right()) | |
override fun fetchAccount(): IO<AccountEntity> = | |
IO.async { _, callback -> | |
retrofit(callback) | |
} | |
} | |
interface Domain { | |
fun <R> R.getProcessedAccount(): IO<Account> where R: Data | |
} | |
class DefaultDomain : Domain { | |
override fun <R> R.getProcessedAccount(): IO<Account> where R: Data = | |
fetchAccount().map { Account(it.balance) } | |
} | |
interface UI { | |
fun <R> R.present(): IO<Unit> where R: Domain, R: Data | |
} | |
class DefaultUI : UI { | |
override fun <R> R.present(): IO<Unit> where R: Domain, R: Data = | |
fx { | |
val account = getProcessedAccount().bind() | |
!effect { println(account) } | |
} | |
} | |
class Module( | |
data: Data = InMemoryData(), | |
domain: Domain = DefaultDomain(), | |
val ui: UI = DefaultUI() | |
) : Data by data, UI by ui, Domain by domain { | |
companion object { | |
val defaultInstance = Module() | |
} | |
} | |
fun main() { | |
with(Module.defaultInstance) { | |
present().unsafeRunSync() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment