Я использую Arrow в своем бэкэнд-проекте Kotlin.У меня есть такие репозитории:
interface UserRepository {
fun user(username: String): Try<Option<User>>
}
Теперь я хочу пойти дальше и абстрагироваться от конкретного типа Try
с возвратом Kind<F, Option<User>>
.Я смог сделать это с помощью этого кода:
interface UserRepository<F> {
fun user(username: String): Kind<F, Option<User>>
}
class IdRepository : UserRepository<ForId> {
fun user(username: String): Kind<ForId<Option<User>>> =
if (username == "known") Id.just(Some(User()))
else Id.just(None)
}
Но сейчас я изо всех сил пытаюсь его использовать.Я не понимаю, как мы можем сказать, что F
в userRepository
должна быть монадой, чтобы ее можно было использовать в блоке понимания монады.Предположим, у меня есть некоторый класс, определенный следующим образом:
class UserService<F>(ME: MonadError<F, Throwable>, repo: UserRepository<F>)
: MonadError<F, Throwable> by ME {
fun someOperations(username: String) : Kind<F, User> = bindingCatch {
val (user) = repo.user(username)
user.fold({ /* create user */ }, { /* return user */ })
}
}
Компилятор жалуется, что он не может связать user
в строке repo.user
, так как для него требуется Kind<ForTry, ...>
, но repo.user
возвращает Kind<F, ...>
что здесь неизвестноКак правильно добиться абстракции от Try
, чтобы я мог реализовать репозитории с Id
экземплярами и как использовать такие репозитории в классах обслуживания?