【问题标题】:How to abstract from Try in arrow-kt如何从 Try in arrow-kt 中抽象出来
【发布时间】:2019-09-21 09:19:51
【问题描述】:

我在我的 Kotlin 后端项目中使用 Arrow。我有这样的存储库:

interface UserRepository {
  fun user(username: String): Try<Option<User>>
}

现在我想更进一步,从具体的Try 类型中抽象出来,而是返回Kind&lt;F, Option&lt;User&gt;&gt;。我可以用这段代码做到这一点:

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)
}

但现在我很难使用它。我不明白我们怎么能说userRepository 中的F 必须是Monad,这样它才能在monad 理解块中使用。假设我有一些这样定义的类:

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 */ })
  }
}

编译器抱怨它无法在repo.user 上绑定user,因为它需要Kind&lt;ForTry, ...&gt;,但repo.user 返回Kind&lt;F, ...&gt;,此处未知。如何正确实现从 Try 的抽象,以便我可以使用 Id 实例实现存储库以及如何在服务类中使用此类存储库?

【问题讨论】:

    标签: kotlin arrow-kt


    【解决方案1】:

    在 0.10.0 中,您可以使用 Fx 类型类来执行 monad 绑定。如您的示例中的 kdoc 中所述,它的变体可用,其中每个变体都代表您想要的功率级别。实际上,大多数应用程序使用IO.fx,因为效果只能纯粹封装在IO 中。如果您正在处理副作用,您只能替换运行时,只要它们支持暂停,因此这基本上将您的运行时选项缩小到 Async&lt;F&gt; 的实例,因为暂停意味着潜在的异步工作。即 IO、Rx 等……但从不尝试、任何一个……这些对于急切的非有效纯计算很有用

    /**
     * Fx allows you to run pure sequential code as if it was imperative.
     *
     * @see [arrow.typeclasses.suspended.monad.Fx] // Anything with flatMap
     * @see [arrow.typeclasses.suspended.monaderror.Fx] //Try, Either etc stop here
     * @see [arrow.fx.typeclasses.suspended.monaddefer.Fx] // IO
     * @see [arrow.fx.typeclasses.suspended.concurrent.Fx] // IO
     */
    class UserService<F>(ME: MonadError<F, Throwable>, repo: UserRepository<F>) 
      : MonadError<F, Throwable> by ME {
    
      fun someOperations(username: String) : Kind<F, User> = 
        fx.monadThrow {
          val user = !repo.user(username)
          user.fold({ /* create user */ }, { /* return user */ })
        }
      }
    
    }
    

    如果您想通过https://slack.kotlinlang.org #arrow 频道获得更详细的解释,我们很乐意为您提供帮助并在 Kotlin 中闲逛和讨论 FP

    干杯!

    【讨论】:

      猜你喜欢
      • 2019-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-14
      • 1970-01-01
      相关资源
      最近更新 更多