рдПрд░реЛ рдХреЗ рд╕рд╛рде рдмрд╣реБрд░реВрдкреА рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВ



рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░!

рдореЗрд░рд╛ рдирд╛рдо рдПрд░реНрдЯреЛрдо рдбреЛрдмреНрд░реЛрд╡рд┐рдВрд╕реНрдХреА рд╣реИ, рдореИрдВ рдлрд┐рдВрдЪ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВред рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдмрд╣реБрд░рдВрдЧреА рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП Arrow рдлрдВрдХреНрд╢рдирд▓ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдкрд┐рддрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдиреЗ рдПрдХ рд▓реЗрдЦ рдкрдврд╝рд╛ред рдЕрдХреНрд╕рд░ рдЬреЛ рд▓реЛрдЧ рдХреЗрд╡рд▓ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╢реИрд▓реА рдореЗрдВ рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╡реЗ рдкреБрд░рд╛рдиреА рдЖрджрддреЛрдВ рдХреЗ рд╕рд╛рде рднрд╛рдЧ рд▓реЗрдиреЗ рдХреА рдЬрд▓реНрджреА рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВ, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдбреАрдЖрдИ рдХрдВрдЯреЗрдирд░ рдФрд░ рд╡рд┐рд░рд╛рд╕рдд рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдЕрдирд┐рд╡рд╛рд░реНрдпрддрд╛ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдХрдИ рд▓реЛрдЧреЛрдВ рдХреЛ рд╕рд╣реА рджрд┐рд╢рд╛ рдореЗрдВ рд╕реЛрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдХрд╛ рдЖрдирдВрдж рд▓реЗрдВ!


***


рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪреЗ рдмрд┐рдирд╛ рдЖрд╡реЗрджрди рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдмрд╕ рдпрд╣ рд╡рд░реНрдгрди рдХрд░реЗрдВ рдХрд┐ рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рдХреИрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛?


рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ рдЬреЛ RxJava рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдСрдмреНрдЬрд░реНрд╡реЗрдмрд▓ рдЯрд╛рдЗрдк рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдкреНрд░рдХрд╛рд░ рд╣рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХреЙрд▓ рдФрд░ рдореИрдирд┐рдкреБрд▓реЗрд╢рди рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдВрдд рдореЗрдВ, рдХреНрдпрд╛ рдпрд╣ Observable рдХреЗрд╡рд▓ рдЕрддрд┐рд░рд┐рдХреНрдд рдЧреБрдгреЛрдВ рд╡рд╛рд▓рд╛ рдХрдВрдЯреЗрдирд░ рдирд╣реАрдВ рд╣реЛрдЧрд╛?


Flowable , Flowable ( Flowable ), Future , IO рдФрд░ рдХрдИ рдЕрдиреНрдп рдЬреИрд╕реЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдХрд╣рд╛рдиреАред


рд╡реИрдЪрд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ, рдпреЗ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдПрдХ рдСрдкрд░реЗрд╢рди рд╣реИ (рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд▓рд╛рдЧреВ рд╣реЛрдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдпрд╛ рдмрдирд╛рдИ рдЧрдИ рд╣реИ) рдЬреЛ рдПрдХ рджреВрд╕рд░реЗ рдкреНрд░рдХрд╛рд░ ( map ) рдХреЗ рд▓рд┐рдП рдЖрдВрддрд░рд┐рдХ рдореВрд▓реНрдп рдХреЛ рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛрдбрд╝рддреЛрдбрд╝ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдХрд░рддреЗ рд╣реБрдП рдЗрд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП flatMap рдХрд╛ рдЙрдкрдпреЛрдЧ flatMap ( zip ), рдЖрджрд┐ред


рдЗрди рд╡реНрдпрд╡рд╣рд╛рд░реЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдШреЛрд╖рдгрд╛рддреНрдордХ рд╡рд┐рд╡рд░рдг рдмрдирд╛рдП рд░рдЦрддреЗ рд╣реБрдП, рдФрд░ рдЖрдкрдХреЗ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдЬреИрд╕реЗ рдХрд┐ flatMap рд╕реНрд╡рддрдВрддреНрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП Observable рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреБрдЫ рдЕрдиреБрдмрдВрдзреЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ map , flatMap рдФрд░ рдЕрдиреНрдпред ред


рдРрд╕рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЕрдЬреАрдм рдпрд╛ рдмрд╣реБрдд рдЬрдЯрд┐рд▓ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рджрд┐рд▓рдЪрд╕реНрдк рдлрд╛рдпрджреЗ рд╣реИрдВред рдкрд╣рд▓реЗ, рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдФрд░ рдлрд┐рд░ рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВред


рд╡рд┐рд╣рд┐рдд рд╕рдорд╕реНрдпрд╛


рдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЯреВ-рдбреВ рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдПрдХ рдЖрд╡реЗрджрди рд╣реИ, рдФрд░ рд╣рдо рд╕реНрдерд╛рдиреАрдп рдХреИрд╢ рд╕реЗ рдЯрд╛рдЗрдк Task рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдирд┐рдХрд╛рд▓рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗред рдпрджрд┐ рд╡реЗ рд╕реНрдерд╛рдиреАрдп рд╕рдВрдЧреНрд░рд╣рдг рдореЗрдВ рдирд╣реАрдВ рдкрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдХреНрд╡реЗрд░реА рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗред рд╣рдореЗрдВ рджреЛрдиреЛрдВ рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХрд▓ рдЕрдиреБрдмрдВрдз рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рджреЛрдиреЛрдВ рдХреЛ рд╕реНрд░реЛрдд рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдЙрдкрдпреБрдХреНрдд User рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк Task рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕реВрдЪреА рдорд┐рд▓ рд╕рдХреЗ:


 interface DataSource { fun allTasksByUser(user: User): Observable<List<Task>> } 

рдпрд╣рд╛рдБ, рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рд╣рдо Flowable , рд▓реЗрдХрд┐рди рдпрд╣ Single , Maybe , Flowable , Deferred - рд▓рдХреНрд╖реНрдп рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реЛред


рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХреЗ рдореЛрдЪрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреЛ рдЬреЛрдбрд╝реЗрдВ, рдПрдХ рдФрд░ рдПрдХ ред


 class LocalDataSource : DataSource { private val localCache: Map<User, List<Task>> = mapOf(User(UserId("user1")) to listOf(Task("LocalTask assigned to user1"))) override fun allTasksByUser(user: User): Observable<List<Task>> = Observable.create { emitter -> val cachedUser = localCache[user] if (cachedUser != null) { emitter.onNext(cachedUser) } else { emitter.onError(UserNotInLocalStorage(user)) } } } class RemoteDataSource : DataSource { private val internetStorage: Map<User, List<Task>> = mapOf(User(UserId("user2")) to listOf(Task("Remote Task assigned to user2"))) override fun allTasksByUser(user: User): Observable<List<Task>> = Observable.create { emitter -> val networkUser = internetStorage[user] if (networkUser != null) { emitter.onNext(networkUser) } else { emitter.onError(UserNotInRemoteStorage(user)) } } } 

рджреЛрдиреЛрдВ рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рдЧрднрдЧ рд╕рдорд╛рди рд╣реИред рдпреЗ рдЗрди рд╕реНрд░реЛрддреЛрдВ рдХреЗ рдХреЗрд╡рд▓ рдирдХрд▓реА рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВ рдЬреЛ рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рд╕реНрдерд╛рдиреАрдп рднрдВрдбрд╛рд░рдг рдпрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдПрдкреАрдЖрдИ рд╕реЗ рдбреЗрдЯрд╛ рдЦреАрдВрдЪрддреЗ рд╣реИрдВред рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, Map<User, List<Task>> рдХрд╛ рдЙрдкрдпреЛрдЧ рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдбреЗрдЯрд╛ рдХреЗ рджреЛ рд╕реНрд░реЛрдд рд╣реИрдВ, рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдХрд┐рд╕реА рддрд░рд╣ рд╕рдордиреНрд╡рдпрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдПрдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдмрдирд╛рдПрдБ:


 class TaskRepository(private val localDS: DataSource, private val remoteDS: RemoteDataSource) { fun allTasksByUser(user: User): Observable<List<Task>> = localDS.allTasksByUser(user) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) .onErrorResumeNext { _: Throwable -> remoteDS.allTasksByUser(user) } } 

рдпрд╣ рдХреЗрд╡рд▓ LocalDataSource рд╕реЗ List<Task> рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдпрд╣ рдирд╣реАрдВ рдкрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ LocalDataSource рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред


рдЪрд▓реЛ рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди (DI) рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдирд┐рд░реНрднрд░рддрд╛ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдореЙрдбреНрдпреВрд▓ рдмрдирд╛рдПрдБ:


 class Module { private val localDataSource: LocalDataSource = LocalDataSource() private val remoteDataSource: RemoteDataSource = RemoteDataSource() val repository: TaskRepository = TaskRepository(localDataSource, remoteDataSource) } 

рдФрд░ рдЕрдВрдд рдореЗрдВ, рд╣рдореЗрдВ рдПрдХ рд╕рд░рд▓ рдкрд░реАрдХреНрд╖рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдкреВрд░реЗ рдвреЗрд░ рдХреЛ рдЪрд▓рд╛рддрд╛ рд╣реИ:


 object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val dependenciesModule = Module() dependenciesModule.run { repository.allTasksByUser(user1).subscribe({ println(it) }, { println(it) }) repository.allTasksByUser(user2).subscribe({ println(it) }, { println(it) }) repository.allTasksByUser(user3).subscribe({ println(it) }, { println(it) }) } } } 

рдЙрдкрд░реЛрдХреНрдд рд╕рднреА рдХреЛрдб рдЬреАрдердм рдкрд░ рдкрд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ ред


рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд░рдо рддреАрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдкрд╛рджрди рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреА рд░рдЪрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдлрд┐рд░ рдкрд░рд┐рдгрд╛рдореА Observable рд▓рд┐рдП рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрддрд╛ рд╣реИред


User рдкрд╣рд▓реЗ рджреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдЙрдкрд▓рдмреНрдз рд╣реИрдВ, рдЗрд╕рдХреЗ рд╕рд╛рде рд╣рдо рднрд╛рдЧреНрдпрд╢рд╛рд▓реА рдереЗред User1 рд╕реНрдерд╛рдиреАрдп DataSource рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдФрд░ User2 рд░рд┐рдореЛрдЯ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред


рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ 3 рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕реНрдерд╛рдиреАрдп рднрдВрдбрд╛рд░рдг рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИред рдХрд╛рд░реНрдпрдХреНрд░рдо рдЗрд╕реЗ рджреВрд░рд╕реНрде рд╕реЗрд╡рд╛ рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдЧрд╛ - рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд╣рд╛рдВ рднреА рдирд╣реАрдВ рд╣реИред рдЦреЛрдЬ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧреА, рдФрд░ рд╣рдо рдХрдВрд╕реЛрд▓ рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВрдЧреЗред


рдпрд╣рд╛рдБ рддреАрдиреЛрдВ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрдВрд╕реЛрд▓ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:


 > [Task(value=LocalTask assigned to user1)] > [Task(value=Remote Task assigned to user2)] > UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))) 

рд╣рдо рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдм рдЗрд╕ рддрд░реНрдХ рдХреЛ рдХреА рд╢реИрд▓реА рдореЗрдВ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред


рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдЕрдореВрд░реНрдд


рдЕрдм DataSource рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЕрдиреБрдмрдВрдз рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:


 interface DataSource<F> { fun allTasksByUser(user: User): Kind<F, List<Task>> } 

рд╕рдм рдХреБрдЫ рд╕рдорд╛рди рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рджреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрдВрддрд░ рд╣реИрдВ:


  • рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдкреНрд░рдХрд╛рд░ (рдЬреЗрдиреЗрд░рд┐рдХ) F рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рд╣реИ F
  • рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ рдкреНрд░рдХрд╛рд░ рдЕрдм Kind<F, List<Task>> ред

Kind рдПрд░реЛ рдХреЛ рдХрд┐рд╕ Kind рд╕реЗ рдПрдирдХреЛрдб рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдорддреМрд░ рдкрд░ рдПрдХ (higher kind) рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ
рдореИрдВ рдЗрд╕ рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рд╕рдордЭрд╛рдКрдВрдЧрд╛ред


Observable<A> рдХреЗ 2 рднрд╛рдЧ рд╣реИрдВ:


  • Observable : рдХрдВрдЯреЗрдирд░, рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░рдХрд╛рд░ред
  • A : рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХрд╛ рддрд░реНрдХред рдПрдХ рдЕрдореВрд░реНрдд рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдкрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред

рд╣рдо A рдЬреИрд╕реЗ рд╕рд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдмрд╣реБрдд рд╕реЗ рд▓реЛрдЧ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо Observable рдХрдВрдЯреЗрдирд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рднреА рдкрд╛рд▓рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рд╣реИрдВред


рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ F<A> рдЬреИрд╕рд╛ рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ F рдФрд░ A рджреЛрдиреЛрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЕрднреА рддрдХ рдХреЛрдЯрд▓рд┐рди рдХрдВрдкрд╛рдЗрд▓рд░ ( рдЕрднреА рднреА? ) рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рдПрдХ рд╕рдорд╛рди рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рдирдХрд▓ рдХрд░реЗрдВрдЧреЗред


рдПрд░реЛ рдПрдХ рдЗрдВрдЯрд░рдореАрдбрд┐рдПрдЯ рдореЗрдЯрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ Kind<F, A> рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдВрдХ рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рджреЛрдиреЛрдВ рджрд┐рд╢рд╛рдУрдВ рдореЗрдВ рдХрдиреНрд╡рд░реНрдЯрд░реНрд╕ рднреА рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЖрдк Kind<Observable, List<Task>> рд╕реЗ рдкрде рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░ рд╕рдХреЗрдВред Kind<Observable, List<Task>> Observable<List<Task>> рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрддред рдПрдХ рдЖрджрд░реНрд╢ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред


рддреЛ рдлрд┐рд░, рд╣рдорд╛рд░реЗ рднрдВрдбрд╛рд░ рдХрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рджреЗрдЦреЗрдВ:


 interface DataSource<F> { fun allTasksByUser(user: User): Kind<F, List<Task>> } 

DataSource рдлрд╝рдВрдХреНрд╢рди рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рджреЗрддрд╛ рд╣реИ: Kind<F, List<Task>> ред рдпрд╣ F<List<Task>> , рдЬрд╣рд╛рдВ F рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рд░рд╣рддрд╛ рд╣реИред


рд╣рдо рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдореЗрдВ рдХреЗрд╡рд▓ List<Task> рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рддреЗ рд╣реИрдВред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рд╣рдо рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ F рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрдм рддрдХ рдХрд┐ рдЗрд╕рдореЗрдВ рдПрдХ List<Task> ред рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдбреЗрдЯрд╛ рдХрдВрдЯреЗрдирд░ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реНрдкрд╖реНрдЯ рд╣реИ? рдЖрдЧреЗ рдмрдврд╝реЛред


рдЖрдЗрдП рдЗрд╕ рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП DataSource рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ, рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рд░ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рд╕реНрдерд╛рдиреАрдп:


 class LocalDataSource<F>(A: ApplicativeError<F, Throwable>) : DataSource<F>, ApplicativeError<F, Throwable> by A { private val localCache: Map<User, List<Task>> = mapOf(User(UserId("user1")) to listOf(Task("LocalTask assigned to user1"))) override fun allTasksByUser(user: User): Kind<F, List<Task>> = Option.fromNullable(localCache[user]).fold( { raiseError(UserNotInLocalStorage(user)) }, { just(it) } ) } 

рдмрд╣реБрдд рд╕реА рдирдИ рдЪреАрдЬреЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдо рд╣рд░ рдЪреАрдЬ рдХрд╛ рдЪрд░рдг рджрд░ рдЪрд░рдг рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗред


рдпрд╣ DataSource рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ F рдмрдирд╛рдП рд░рдЦрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ DataSource<F> рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рд╣рдо рдмрд╛рд╣рд░ рд╕реЗ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреНрд░рд╕рд╛рд░рдг рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд░рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред


рдЕрдм, рдирд┐рд░реНрдорд╛рддрд╛ рдореЗрдВ рд╕рдВрднрд╡рддрдГ рдЕрдкрд░рд┐рдЪрд┐рдд allTasksByUser() рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рдЬрд╛рдПрдВ рдФрд░ allTasksByUser() рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдВред рдФрд░ рд╣рдо рдРрдкреНрд▓реАрдХреЗрд╢рди рдкрд░ рд▓реМрдЯ рдЖрдПрдВрдЧреЗред


 override fun allTasksByUser(user: User): Kind<F, List<Task>> = Option.fromNullable(localCache[user]).fold( { raiseError(UserNotInLocalStorage(user)) }, { just(it) } ) 

рдпрд╣ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ Kind<F, List<Task>> ред рд╣рдореЗрдВ рдЕрднреА рднреА рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХрдВрдЯреЗрдирд░ F рдХреНрдпрд╛ F рдЬрдм рддрдХ рдХрд┐ рдЗрд╕рдореЗрдВ рдПрдХ List<Task> ред


рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреЗ рд╣реБрдП рдХрд┐ рд╣рдо рд╕реНрдерд╛рдиреАрдп рд╕реНрдЯреЛрд░реЗрдЬ рдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП Task рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдирд╣реАрдВ, рд╣рдо рдПрдХ рддреНрд░реБрдЯрд┐ (рдХреЛрдИ Task рдирд╣реАрдВ рдорд┐рд▓рд╛) рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдпрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЯрд╛ рдореЗрдВ рд▓рд┐рдкрдЯреЗ Task ( Task рдкрд╛рдпрд╛ рдЧрдпрд╛) рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред


рдФрд░ рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╣рдореЗрдВ рд▓реМрдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: Kind<F, List<Task>> ред


рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ: рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо ( F ) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рдФрд░ рд╣рдореЗрдВ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рд╕реЗ рд▓рд┐рдкрдЯреЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд╛рд╕реНрддрд╛ рдЪрд╛рд╣рд┐рдПред рд╕рд╛рде рд╣реА, рд╣рдореЗрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдлрд▓ рд╕рдорд╛рдкрди рдХреЗ рдмрд╛рдж рдкреНрд░рд╛рдкреНрдд рдореВрд▓реНрдп рдХреЛ рд▓рдкреЗрдЯрд╛ рдЬрд╛рдПрдЧрд╛ред рдХреБрдЫ рдЕрд╕рдВрднрд╡ рдЬреИрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ?


рдЖрдЗрдП рдХрдХреНрд╖рд╛ рдХреА рдШреЛрд╖рдгрд╛ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ рдФрд░ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдПрдкреНрд▓рд┐рдХреЗрдЯрд░ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдХрдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХреЗ рд░реВрдк рдореЗрдВ ( by A ) by A рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


 class LocalDataSource<F>(A: ApplicativeError<F, Throwable>) : DataSource<F>, ApplicativeError<F, Throwable> by A { //... } 

ApplicativeError рдПрдкреЗрд░реЗрдЯрд┐рд╡ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд ApplicativeError рдорд┐рд▓рд╛ рд╣реИ, рджреЛрдиреЛрдВ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡рд░реНрдЧ рд╣реИрдВред


рдкреНрд░рдХрд╛рд░ рдХрдХреНрд╖рд╛рдПрдВ рд╡реНрдпрд╡рд╣рд╛рд░ (рдЕрдиреБрдмрдВрдз) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреА рд╣реИрдВред рд╡реЗ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдиреНрдХреЛрдбреЗрдб рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ Monad<F> , Functor<F> рдФрд░ рдХрдИ рдЕрдиреНрдп рдореЗрдВред рдпрд╣ F рдПрдХ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИред рдЗрд╕ рддрд░рд╣, рд╣рдо Either , Option , IO , Flowable рдФрд░ рдХрдИ рдФрд░ рдЕрдзрд┐рдХ рдкреНрд░рдХрд╛рд░ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реА рджреЛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ:


  • рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ Kind<F, List<Task>> рдореЗрдВ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдкреНрд░рд╛рдкреНрдд рдорд╛рди рд▓рдкреЗрдЯреЗрдВ

рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ Applicative рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЪреВрдБрдХрд┐ рдПрдкреНрд▓реАрдХреЗрдЯрд░ рдЗрд╕ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд ApplicativeError рдорд┐рд▓рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдХреЗ рдЧреБрдгреЛрдВ рдХреЛ рд╕реМрдВрдк рд╕рдХрддреЗ рд╣реИрдВред


Applicative рд╕рд┐рд░реНрдл just(a) рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред just(a) рдХрд┐рд╕реА рднреА рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдореВрд▓реНрдп рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Applicative<F> , рддреЛ рдХрдВрдЯреЗрдирд░ F рдореЗрдВ рдореВрд▓реНрдп рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХреЗ рд▓рд┐рдП just(a) рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рднреА рдЙрд╕ рдореВрд▓реНрдп рдХрд╛ рд╣реИред рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдо Observable рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ Applicative<Observable> рдЬреЛ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдПрдХ Observable рдореЗрдВ рдХреИрд╕реЗ рд▓рдкреЗрдЯреЗрдВ, рддрд╛рдХрд┐ рд╣рдореЗрдВ Observable.just(a) ред


  • рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рддреНрд░реБрдЯрд┐ рд▓рдкреЗрдЯреЗрдВ Kind<F, List<Task>>

рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо ApplicativeError рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдПрдХ рдлрд╝рдВрдХреНрд╢рди raiseError(e) , рдЬреЛ рдЯрд╛рдЗрдк F рдХрдВрдЯреЗрдирд░ рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИ F Observable рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рддреНрд░реБрдЯрд┐ Observable.error<A>(t) рддрд░рд╣ рдХреБрдЫ Observable.error<A>(t) , рдЬрд╣рд╛рдВ t Throwable , рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдЕрдкрдиреА рддреНрд░реБрдЯрд┐ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ ApplicativeError<F, Throwable> рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ ApplicativeError<F, Throwable> ред


LocalDataSource<F> рд╣рдорд╛рд░реЗ рдЕрдореВрд░реНрдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред


 class LocalDataSource<F>(A: ApplicativeError<F, Throwable>) : DataSource<F>, ApplicativeError<F, Throwable> by A { private val localCache: Map<User, List<Task>> = mapOf(User(UserId("user1")) to listOf(Task("LocalTask assigned to user1"))) override fun allTasksByUser(user: User): Kind<F, List<Task>> = Option.fromNullable(localCache[user]).fold( { raiseError(UserNotInLocalStorage(user)) }, { just(it) } ) } 

рд╕реНрдореГрддрд┐ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд Map<User, List<Task>> рд╕рдорд╛рди рд░рд╣рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдм рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХреБрдЫ рдРрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЗ рд▓рд┐рдП рдирдП рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:


  • рд╡рд╣ рд╕реНрдерд╛рдиреАрдп рдХреИрд╢ рд╕реЗ Task рд╕реВрдЪреА рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЪреВрдВрдХрд┐ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп null рд╣реЛ рд╕рдХрддрд╛ рд╣реИ ( Task рдирд╣реАрдВ рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ), рд╣рдо Option рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдореЙрдбрд▓ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ Option рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЙрд╕ рдореВрд▓реНрдп рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдпрд╛ рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдЬреЛ рдЗрд╕рдореЗрдВ рд▓рд┐рдкрдЯреЗ рд╣реБрдП рд╣реИрдВред


  • рд╡реИрдХрд▓реНрдкрд┐рдХ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЗрд╕рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ fold рдХрд╣рддреЗ рд╣реИрдВред рдпрд╣ рд╡реИрдХрд▓реНрдкрд┐рдХ рдорд╛рди рдкрд░ when рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдпрджрд┐ рдорд╛рди рдЧрд╛рдпрдм рд╣реИ, рддреЛ Option рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ F (рдкрд╣рд▓реЗ рд▓рдВрдмреЛ рдкрд╛рд╕) рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдФрд░ рдпрджрд┐ рдорд╛рди рдореМрдЬреВрдж рд╣реИ, рддреЛ Option рдбреЗрдЯрд╛ рдЯрд╛рдЗрдк F (рджреВрд╕рд░рд╛ рд▓реИрдореНрдмреНрдбрд╛) рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд░рдг рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддрд╛ рд╣реИред рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдкрд╣рд▓реЗ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА raiseError() рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: raiseError() рдФрд░ just() ред



рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдордиреЗ рдХрдХреНрд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбреЗрдЯрд╛ рд╕реНрд░реЛрддреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЕрдореВрд░реНрдд рдХрд░ рджрд┐рдпрд╛ рддрд╛рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдпрд╣ рдкрддрд╛ рди рдЪрд▓реЗ рдХрд┐ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ F рд▓рд┐рдП рдХрдВрдЯреЗрдирд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдиреЗрдЯрд╡рд░реНрдХ DataSource рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 class RemoteDataSource<F>(A: Async<F>) : DataSource<F>, Async<F> by A { private val internetStorage: Map<User, List<Task>> = mapOf(User(UserId("user2")) to listOf(Task("Remote Task assigned to user2"))) override fun allTasksByUser(user: User): Kind<F, List<Task>> = async { callback: (Either<Throwable, List<Task>>) -> Unit -> Option.fromNullable(internetStorage[user]).fold( { callback(UserNotInRemoteStorage(user).left()) }, { callback(it.right()) } ) } } 

рд▓реЗрдХрд┐рди рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЕрдВрддрд░ рд╣реИ: рдПрдкреНрд▓рд┐рдХреЗрд░рд┐рдпрд▓ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдПрдХ рдЕрдиреНрдп рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдЬреИрд╕реЗ: Async ред


рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдиреЗрдЯрд╡рд░реНрдХ рдХреЙрд▓ рдкреНрд░рдХреГрддрд┐ рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╣реИрдВред рд╣рдо рдХреЛрдб рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд░реВрдк рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдП рдЧрдП рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реИред


рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдХрд┐рд╕реА рднреА рдХреЙрд▓рдмреИрдХ рдСрдкрд░реЗрд╢рди рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо рдЕрднреА рднреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ, рд╣рдо рдмрд╕ рдкреНрд░рдХреГрддрд┐ рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдПрдХ рдСрдкрд░реЗрд╢рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:


 override fun allTasksByUser(user: User): Kind<F, List<Task>> = async { callback: (Either<Throwable, List<Task>>) -> Unit -> Option.fromNullable(internetStorage[user]).fold( { callback(UserNotInRemoteStorage(user).left()) }, { callback(it.right()) } ) } 

рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ async {} рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рд╣рдореЗрдВ рдСрдкрд░реЗрд╢рди рдХреЛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк Async рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рдХрд╛рд░ Kind<F, List<Task>> рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддрд╛ рд╣реИ Kind<F, List<Task>> рдЬрд┐рд╕реЗ asynchronously рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдпрджрд┐ рд╣рдо рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рдХрд┐ Async.async {} , Async.async {} Observable.create() , рдпрд╛рдиреА рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛ред рдПрдХ рдСрдкрд░реЗрд╢рди рдмрдирд╛рдирд╛, рдЬрд┐рд╕реЗ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдпрд╛ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХреЛрдб рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреИрд╕реЗ Thread рдпрд╛ AsyncTask ред


callback рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд░рд┐рдгрд╛рдореА рдХреЙрд▓рдмреИрдХ рдХреЛ рдХрдВрдЯреЗрдирд░ рд╕рдВрджрд░реНрдн F рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рд╣реИред


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдорд╛рд░рд╛ RemoteDataSource рд╕рд╛рд░ рд╣реИ рдФрд░ рдЕрднреА рднреА F рдЕрдЬреНрдЮрд╛рдд рдХрдВрдЯреЗрдирд░ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ F


рдЪрд▓рд┐рдП рдПрдмреНрд╕рдЯреНрд░реИрдХреНрд╢рди рдХреЗ рд╕реНрддрд░ рддрдХ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рд╣рдорд╛рд░реА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдкрд░ рдПрдХ рдФрд░ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреЛ рдпрд╛рдж рд╣реИ, рддреЛ рдкрд╣рд▓реЗ рд╣рдореЗрдВ LocalDataSource рдореЗрдВ Task рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ рддрдм (рдпрджрд┐ рд╡реЗ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдирд╣реАрдВ рдорд┐рд▓реЗ рдереЗ) RemoteLocalDataSource рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред


 class TaskRepository<F>( private val localDS: DataSource<F>, private val remoteDS: RemoteDataSource<F>, AE: ApplicativeError<F, Throwable>) : ApplicativeError<F, Throwable> by AE { fun allTasksByUser(user: User): Kind<F, List<Task>> = localDS.allTasksByUser(user).handleErrorWith { when (it) { is UserNotInLocalStorage -> remoteDS.allTasksByUser(user) else -> raiseError(UnknownError(it)) } } } 

ApplicativeError<F, Throwable> рдлрд┐рд░ рд╕реЗ рд╣рдорд╛рд░реЗ рд╕рд╛рде рд╣реИ! рдпрд╣ рдХрд┐рд╕реА рднреА рдЙрдЪреНрдЪ рдЕрдВрдд рд░рд┐рд╕реАрд╡рд░ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдлрд╝рдВрдХреНрд╢рди handleErrorWith() рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред


рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 fun <A> Kind<F, A>.handleErrorWith(f: (E) -> Kind<F, A>): Kind<F, A> 

рдХреНрдпреЛрдВрдХрд┐ localDS.allTasksByUser(user) Kind<F, List<Task>> рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИ Kind<F, List<Task>> , рдЬрд┐рд╕реЗ F<List<Task>> рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ F рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдмрдирд╛ рд╣реБрдЖ рд╣реИ, рд╣рдо рдЗрд╕рдХреЗ рдКрдкрд░ рд╕реЗ handleErrorWith() рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


handleErrorWith() рдЖрдкрдХреЛ рдЧреБрдЬрд╝рд░реЗ рд╣реБрдП рд▓реИрдореНрдмреНрдбрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЪрд▓реЛ рд╕рдорд╛рд░реЛрд╣ рдкрд░ рдПрдХ рдХрд░реАрдм рджреЗрдЦреЛ:


 fun allTasksByUser(user: User): Kind<F, List<Task>> = localDS.allTasksByUser(user).handleErrorWith { when (it) { is UserNotInLocalStorage -> remoteDS.allTasksByUser(user) else -> raiseError(UnknownError(it)) } } 

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдореЗрдВ рдкрд╣рд▓реЗ рдСрдкрд░реЗрд╢рди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдорд┐рд▓рддрд╛ рд╣реИ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ рдЬрдм рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЕрдкрд╡рд╛рдж рд▓рд╛рдВрдмрд╛ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рддреНрд░реБрдЯрд┐ UserNotInLocalStorage рдкреНрд░рдХрд╛рд░ рдХреА рд╣реИ, рддреЛ рд╣рдо UserNotInLocalStorage рдореЗрдВ Tasks рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗред рдЕрдиреНрдп рд╕рднреА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╣рдо рдЕрдЬреНрдЮрд╛рдд рддреНрд░реБрдЯрд┐ рдХреЛ F рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд▓рдкреЗрдЯрддреЗ рд╣реИрдВ F


рдирд┐рд░реНрднрд░рддрд╛ рдореЙрдбреНрдпреВрд▓ рдкрд┐рдЫрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рдорд╛рди рд╣реИ:


 class Module<F>(A: Async<F>) { private val localDataSource: LocalDataSource<F> = LocalDataSource(A) private val remoteDataSource: RemoteDataSource<F> = RemoteDataSource(A) val repository: TaskRepository<F> = TaskRepository(localDataSource, remoteDataSource, A) } 

рдЕрдВрддрд░ рдХреЗрд╡рд▓ рдЗрддрдирд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрдм рд╕рд╛рд░ рд╣реИ рдФрд░ F рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдмрд╣реБрд░реВрдкреА рд░рд╣рддрд╛ рд╣реИред рдореИрдВрдиреЗ рд╢реЛрд░ рдХреЗ рд╕реНрддрд░ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдирдмреВрдЭрдХрд░ рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рдирд╣реАрдВ рджрд┐рдпрд╛, рд▓реЗрдХрд┐рди Async рдПрдкреНрдЯреАрдЯреНрдпреВрдЯрд░ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рднреА рд╕реНрддрд░реЛрдВ рдкрд░ рдЗрд╕рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдмрд╣реБрд░реВрдкрддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг


рдЕрдВрдд рдореЗрдВ, рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрдВрдЯреЗрдирд░реЛрдВ ( F ) рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╣реИ рдФрд░ рд╣рдо рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдкреЙрд▓рд┐рдлреЙрд░реНрдорд┐рдЬреНрдо рдХреЗ рдкрд░реАрдХреНрд╖рдг рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЯрд╛рдЗрдк F рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рдкрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЗ рдПрдХ рд╣реА рдЯреБрдХрдбрд╝реЗ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВрдЧреЗ F рдкрд░рд┐рджреГрд╢реНрдп рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬрдм рд╣рдордиреЗ Observable рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред


рдХрд╛рд░реНрдпрдХреНрд░рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рд╣рдо рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╛рд░ рдХреА рд╕реАрдорд╛рдУрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг рдХреЛ рд╡рд╛рдВрдЫрд┐рдд рд░реВрдк рдореЗрдВ рдмрддрд╛ рд╕рдХрддреЗ рд╣реИрдВред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, RxJava рд╕реЗ рдПрдХ рдХрдВрдЯреЗрдирд░ рдХреЗ рд░реВрдк рдореЗрдВ F Single рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред


 object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val singleModule = Module(SingleK.async()) singleModule.run { repository.allTasksByUser(user1).fix().single.subscribe(::println, ::println) repository.allTasksByUser(user2).fix().single.subscribe(::println, ::println) repository.allTasksByUser(user3).fix().single.subscribe(::println, ::println) } } } 

рдЕрдиреБрдХреВрд▓рддрд╛ рдХреЗ рд▓рд┐рдП, рдПрд░реЛ рдкреНрд░рд╕рд┐рджреНрдз рдкреБрд╕реНрддрдХрд╛рд▓рдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ SingleK рд░реИрдкрд░ рд╣реИред рдпреЗ рд░реИрдкрд░ рдЖрдкрдХреЛ рдЙрдЪреНрдЪ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдВрд╕реЛрд▓ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:


 [Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))) 

рдпрджрд┐ Observable рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рддреЛ рд╡рд╣реА рдкрд░рд┐рдгрд╛рдо рд╣реЛрдЧрд╛ред


рдЕрдм рдЖрдЗрдП, Maybe рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП Maybe MaybeK рд░реИрдкрд░ MaybeK :


 @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val maybeModule = Module(MaybeK.async()) maybeModule.run { repository.allTasksByUser(user1).fix().maybe.subscribe(::println, ::println) repository.allTasksByUser(user2).fix().maybe.subscribe(::println, ::println) repository.allTasksByUser(user3).fix().maybe.subscribe(::println, ::println) } } 

рдПрдХ рд╣реА рдкрд░рд┐рдгрд╛рдо рдХрдВрд╕реЛрд▓ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрдм рдПрдХ рдЕрд▓рдЧ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░:


 [Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))) 

рдХреНрдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ ObservableK / FlowableK ?
рдЖрдЗрдП рдЗрд╕реЗ рдЖрдЬрдорд╛рдПрдБ:


 object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val observableModule = Module(ObservableK.async()) observableModule.run { repository.allTasksByUser(user1).fix().observable.subscribe(::println, ::println) repository.allTasksByUser(user2).fix().observable.subscribe(::println, ::println) repository.allTasksByUser(user3).fix().observable.subscribe(::println, ::println) } val flowableModule = Module(FlowableK.async()) flowableModule.run { repository.allTasksByUser(user1).fix().flowable.subscribe(::println) repository.allTasksByUser(user2).fix().flowable.subscribe(::println) repository.allTasksByUser(user3).fix().flowable.subscribe(::println, ::println) } } } 

рд╣рдо рдХрдВрд╕реЛрд▓ рдореЗрдВ рджреЗрдЦреЗрдВрдЧреЗ:


 [Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))) [Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))) 

рд╕рдм рдХреБрдЫ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред


рдЖрдЗрдП kotlinx.coroutines.Deferred рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдЯрд╛рдЗрдк kotlinx.coroutines.Deferred рд▓рд┐рдП рдПрдХ рдЖрд╡рд░рдгред kotlinx.coroutines.Deferred :


 object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val deferredModule = Module(DeferredK.async()) deferredModule.run { runBlocking { try { println(repository.allTasksByUser(user1).fix().deferred.await()) println(repository.allTasksByUser(user2).fix().deferred.await()) println(repository.allTasksByUser(user3).fix().deferred.await()) } catch (e: UserNotInRemoteStorage) { println(e) } } } } } 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдХреЙрд░рдЯреАрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдЕрдкрд╡рд╛рдж рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред , , .


тАФ :


 [Task(value=LocalTask assigned to user1)] [Task(value=Remote Task assigned to user2)] UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user))) 

Arrow API DeferredK . runBlocking :


 object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val deferredModuleAlt = Module(DeferredK.async()) deferredModuleAlt.run { println(repository.allTasksByUser(user1).fix().unsafeAttemptSync()) println(repository.allTasksByUser(user2).fix().unsafeAttemptSync()) println(repository.allTasksByUser(user3).fix().unsafeAttemptSync()) } } } 

[ Try ]({{ '/docs/arrow/core/try/ru' | relative_url }}) (.., Success Failure ).


 Success(value=[Task(value=LocalTask assigned to user1)]) Success(value=[Task(value=Remote Task assigned to user2)]) Failure(exception=UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user)))) 

, , IO .
IO , in/out , , .


 object test { @JvmStatic fun main(args: Array<String>): Unit { val user1 = User(UserId("user1")) val user2 = User(UserId("user2")) val user3 = User(UserId("unknown user")) val ioModule = Module(IO.async()) ioModule.run { println(repository.allTasksByUser(user1).fix().attempt().unsafeRunSync()) println(repository.allTasksByUser(user2).fix().attempt().unsafeRunSync()) println(repository.allTasksByUser(user3).fix().attempt().unsafeRunSync()) } } } 

 Right(b=[Task(value=LocalTask assigned to user1)]) Right(b=[Task(value=Remote Task assigned to user2)]) Left(a=UserNotInRemoteStorage(user=User(userId=UserId(value=unknown user)))) 

IO тАФ . Either<L,R> ( ). , "" Either , "" , . Right(...) , , Left(...) .


.


, . , , , .


.


тАж ?


, , . .


  • : , (, ), тАФ . , .


  • , . . () ( ) , .


  • (), , (). , .


  • , . , ( ).


  • , API . ( map , flatMap , fold , ). , , Kotlin, Arrow тАФ .


  • DI ( ), .., DI " ". , , . DI, .., , .


  • , , . , .., , .




, .
, , , , .


, . тАФ Twitter: @JorgeCastilloPR .


(, ) :



FP to the max John De Goes FpToTheMax.kt , arrow-examples . , , .

Source: https://habr.com/ru/post/hi447234/


All Articles